Hit Scan Colllsion
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?
--------------------------Sony "Mr. Valdez" ValdezPinoyforum.net Technical EditorPinoyforum.net - the breeding ground of the Filipino Computer Talents
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
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
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia
My Page davepermen.net | My Music on Bandcamp and on Soundcloud
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.
If you want to find where the bullet hits a wall in a level, I suggest using a BSP tree to find the intersection.
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.
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.
--------------------------Sony "Mr. Valdez" ValdezPinoyforum.net Technical EditorPinoyforum.net - the breeding ground of the Filipino Computer Talents
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
- 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
t1 will always be >= t0, because a is always > 0, and sqrt(d) is always > 0
therefore,
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.
Everything is better with Metal.
thanks for the reply, oliii. I''ll try implementing it on my game.
--------------------------Sony "Mr. Valdez" ValdezPinoyforum.net Technical EditorPinoyforum.net - the breeding ground of the Filipino Computer Talents
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.
Watchout for the accuracy of the algorithm. I did that on the top of my head.

Everything is better with Metal.
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.
and I call it like so:
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]
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]
--------------------------Sony "Mr. Valdez" ValdezPinoyforum.net Technical EditorPinoyforum.net - the breeding ground of the Filipino Computer Talents
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
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().
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().
Everything is better with Metal.
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;
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;
Everything is better with Metal.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement