Vector math problem

below is a function that (assuming a bullet impact) is intended to determine if a character was shot from in front or behind.

This is my solution:
1. Calculate length of vectors
2. Calculate the dot product between the two
3. plugin cosine formula to figure out the angle between both vectors

I am wondering what I am doing wrong here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  bool WasShotFromBehind(const Vec3D& bulletVelocity, const Vec3D& CharacterFacing)
{
// bullet vector length
	float bVecLength = sqrt(bulletVelocity.x * bulletVelocity.x + bulletVelocity.y * bulletVelocity.y + bulletVelocity.z * bulletVelocity.z);
	// character vector length
	float cVecLength = sqrt(CharacterFacing.x * CharacterFacing.x + CharacterFacing.y * CharacterFacing.y + CharacterFacing.z * CharacterFacing.z);
	
	// dot product of two vectors
	float dotProduct = bulletVelocity.x * CharacterFacing.x + bulletVelocity.y * CharacterFacing.y + bulletVelocity.z * CharacterFacing.z;

	float cosAngle = dotProduct / (bVecLength * cVecLength);
	if (cosAngle > 0)
            return true;

	return false;
}
do you have the positions of the bullet and char? that is much easier and faster to solve...

I will look deeper but busy for a bit..
Last edited on
It doesn't look wrong. What kind of problems are you having?
Last edited on
it always returns true.

I have a test case with:
CharacterFacing = {0, 0, 1}; // forward
bulletVelocity = { -1, 0, 1};

I believe this should be hitting the character from behind but it always returns true.
If all you need is whether cosAngle is positive or not ... then all you need is whether dotProduct is positive or not - you can avoid actually working out those two square roots.

I should think your function could be reduced to

1
2
3
4
bool WasShotFromBehind(const Vec3D& bulletVelocity, const Vec3D& CharacterFacing)
{
   return bulletVelocity.x * CharacterFacing.x + bulletVelocity.y * CharacterFacing.y + bulletVelocity.z * CharacterFacing.z > 0;
}


I have a test case with:
CharacterFacing = {0, 0, 1}; // forward
bulletVelocity = { -1, 0, 1};

I believe this should be hitting the character from behind but it always returns true.


Well, the dot product of those vectors is 1.0, so it returns true!
0 * (-1) + 0 * 0 + 1 * 1 = 0 + 0 + 1 = 1
Last edited on
No, your code works properly.
You're right, for those coordinates, the bullet is hitting the character from the back so it returns true.

But for coordinates like
CharacterFacing = {0, 0, 1}
bulletVelocity = {-1, 0, -1}
It returns false.

Maybe you're having difficult time generating proper test cases?
Here's a bit of help to visualize it. (A - player, B - bullet)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
  z
  |
  *--x (y points downwards)

  B   A 
   \  | A = (0,  0,  1)
    \#| B = (-1, 0,  1)
     \| O = (0,  0,  0)
      O (angle < pi/2) -> (cos > 0) -> True

      A
      | A = (0,  0,  1)
      | B = (-1, 0 ,-1)
    ##| O = (0,  0,  0)
   ###O (angle > pi/2) -> (cos < 0) -> False
   ##/
    /
   /
  B
Last edited on
Does this mean the fault is in my testing?
I believe this should be hitting the character from behind but it <always> returns true.


You believe this should be hitting the character from behind ...

and a function called WasShotFromBehind returns true ...

so where is the problem?
lastchance is right! You only need to check if dot product is greater than zero making the code that more efficient.

Does this mean the fault is in my testing?

Maybe, since like I said, your code was correct.
If you are making a FPS though, this probably isn't what you want since the bullet can hit you outside your Fov yet it would be detected as a frontal hit (see the picture bellow). And maybe that's why you though it was incorrect?
1
2
3
4
 \ fov /  _B
  \   / _/
   \ /_/
~~~~A~~~~

Perhaps you should elaborate a bit more on what exactly you're trying to do?
Last edited on
thank you all so much
Topic archived. No new replies allowed.