Jump to content
  • Advertisement

Archived

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

s_cloudx

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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
www.google.com

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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*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);



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 found

the same principle applies for triangles and boxes collisions. It''s the principle of ray casting. Fire a ray, calculate the intersection if any.

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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;

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!