#### Archived

This topic is now archived and is closed to further replies.

# Hit Scan Colllsion

This topic is 5498 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

How do I create hit scan (Like in Counter-strike, where all their weapons hit enemies kilometers away at the click of the mouse button) collisions in 3D?

##### Share on other sites
raytracing/raycasting..

think about it. the shoot follows a line. does that line intersect with the world? if so, you hit something. if not, you didn''t. if you hit something, find out what.

"take a look around" - limp bizkit

##### Share on other sites
Basically what you are looking for is an alogrithm for a ray-sphere intersection. Given the vector representing the direction the player is aiming, just find if there is an intersection with the given sphere (defining the bounds of the enemy).

If you want to find where the bullet hits a wall in a level, I suggest using a BSP tree to find the intersection.

##### Share on other sites
Can you please explain a little more on raycasting please?

Im using an octree but since the octree only holds a limited number of game objects I''ve been looking for other techniques. Im planning to put some sniper weapon into the game, btw.

##### Share on other sites
there are loads of docs on the net about ray-casting.

basically, you create a ray, using a start position vector and a direction (normalised), for a sphere/ray intersection, you solve a simple second order equation, it goes like this

  bool Intersect(Vector RayPos, Vector RayDir, Vector SpherePos, float SphereRad, float &t, float tmax){...........................}

- t is the distance of intersection, if it intersects
- tmax is the maximum distance allowed for intersection (this is useful to prioritise collisions. You can simply reset the maximum distance to the last intersection distance found, before testing more objects, which will automatically give you the first intersection in the end).

Ray equation
-------------
P on the ray = RayPos + RayDir * t

Sphere equation
----------------
P on the sphere verifies the equation (P - SpherePos)^2 = SpehreRad^2

so, for a point that is both on a ray and a sphere (i.e. the points of intersection), you replace P by the ray equation

--------------------------------------------------------------
| ((RayPos - SpherePos) + RayDir * t)^ 2 - SphereRad^2 = 0 |
--------------------------------------------------------------

so
[RayDir * RayDir] * t^2 +
[2 * (RayDir * (RayPos - SpherePos))] * t +
[((RayPos - SpherePos)^2 - SphereRad^2] = 0;

you need to solve an equation in the form equation
a.t^2 + b.t + c = 0, so

  c = ((RayPos - SpherePos) * (RayPos - SpherePos)) - (SphereRad * SphereRad);b = 2.0f * (RayDir * (RayPos - SpherePos));a = (RayDir * RayDir);d = b*b - 4*a*cif (d < 0.0f)    return false;if (a < 0.000001f) // this should never happen, but...   return false;t0 = (-b - sqrt(d)) / (2*a);t1 = (-b + sqrt(d)) / (2*a);

t1 will always be >= t0, because a is always > 0, and sqrt(d) is always > 0

therefore,

  if (t1 < 0.0 || t0 > tmax)     return false;else if (t0 > 0.0f)     t = t0;else     t = t1;[source]and in the end, the point of collision on the sphere would be P = RayPos + RayDir * t, if a collision is foundthe same principle applies for triangles and boxes collisions. It''s the principle of ray casting. Fire a ray, calculate the intersection if any.

##### Share on other sites
thanks for the reply, oliii. I''ll try implementing it on my game.

##### Share on other sites
np.

Watchout for the accuracy of the algorithm. I did that on the top of my head. But you get the drift. Solve a simple 2nd order equation. Although 24 hours later, I can''t find anything wrong with what I gave you.

##### Share on other sites
oliii, Something's wrong. I put your code into my game and I'm getting wrong values.

This is the code (off the top of my head. I don't have internet access at home):

Note: I assumed you meant t as a Vector.

      bool Intersect(Vector RayPos, Vector RayDir, Vector SpherePos, float SphereRad, Vector &t, float tmax){ c = ((RayPos - SpherePos) * (RayPos - SpherePos)) - (SphereRad * SphereRad); b = 2.0f * (RayDir * (RayPos - SpherePos)); a = (RayDir * RayDir); d = b*b - 4*a*c; if (d < 0.0f)      return false; if (a < 0.000001f) // this should never happen, but...     return false; t0 = (-b - sqrt(d)) / (2*a); t1 = (-b + sqrt(d)) / (2*a);   if (t1 < 0.0 || t0 > tmax)     return false; else if (t0 > 0.0f)      t = t0; else     t = t1; if (SpherePos == RayPos + RayDir * t) return true;}

and I call it like so:

       if (Intersect(Avatar->Position,               Normalize(Avatar->Camera->LookAt),               Target->Position,               Target->Spheresize,               t,               9999))    DoCollision(Avatar, Target);

btw, I don't understand how d was solved. Can you kindly explain? I appreciate any help.

[edited by - s_cloudx on May 7, 2003 12:47:54 AM]

##### Share on other sites
you got your knickers in a twist...

t is a float, and is the distance from your avatar position to the intersection point.

this is what I would do

  float t_hit = 10000.0f;CTarget* pFirstHitTarget=NULL;for(int i = 0; i < NumberOfTargets; i ++){    float t;    if (Intersect(Avatar->Position,                  Normalize(Avatar->Camera->LookAt),                                 Target[i].Position,                                 Target[i].Spheresize,                                 t,                  t_hit))        {        t_hit = t;        pFirstHitTarget = &Target[i];    }}if (pFirstHitTarget != NULL){   DoCollision(Avatar, pFirstHitTarget, t_hit);}

you can use t_hit in the DoCollision() to apply damage. if t_hit is huge, apply less damage, if it is small (point blank range), apply the maximum damage.

Note, this algo will return the first target hit by the ray. If you want the ray to go through all the targets, you just move the DoCollision() into the if().

##### Share on other sites
OK, as far as the equation is concerned, it''s a scond order equation, in the form

a.x^2 + b.x + c = 0

going back to secondary school, you solve a second order equation by calculating a number d, which is

d = b.b - 4.a.c

if d < 0, there is no solution to the equation (no intersection, the sphere is too far from the ray).

if d > 0, then you will have two possible solutions

x0 = (-b - sqrt(d)) / (2.a)
x1 = (-b + sqrt(d)) / (2.a)

as far as you''re concerned, you''re only interested in the first positive solution. if x0 < 0.0 and x1 < 0.0, then it means that the sphere is behind the avatar, hence no collision.

if x0 < 0.0 and x1 > 0.0, it means that the avatar is INSIde the sphere.

if x0 > 0.0 and x1 > 0.0, it means that the sphere is in front of the ray, and has been intersected in two points. So you take the minimum between the two x0 and x1, and you''ll find the distance of the avatar position to the closest intersection with the sphere.

Basically, take the minimum positive value, that will return the distance of the intersection point to the avatar position.

if you want the intersection point (to do a particle effect), you do

P = Avatar->Position + Normalize(Avatar->Camera->LookAt) * t_hit;

1. 1
2. 2
Rutin
18
3. 3
4. 4
5. 5

• 14
• 12
• 9
• 12
• 37
• ### Forum Statistics

• Total Topics
631431
• Total Posts
3000039
×