Advertisement

Sphere --> Ray intersection?!

Started by March 13, 2002 02:39 PM
10 comments, last by Impz0r 22 years, 10 months ago
Hi, i''m trying to figure out how does an sphere --> ray intersection probably work. I came to this solution, its a copy from an pseudo code, but wont work correctly for me, and i cant figure out why..hmpf ;D Here is the code:
  
eIntersectType cSphereBound::Intersect (const cRay &kRay)
{
 cVector3 Q = kRay.m_kPos-m_kPos;
 Float32 a0 = Dot (Q, Q) - m_fRadius*m_fRadius;
 if (a0 <= 0)
  return (IT_INTERSECT);
 Float32 a1 = Dot (kRay.m_kDir, Q);
 if (a1 >= 0)
  return (IT_OUTSIDE);

 return ((a1*a1 >= a0) ? IT_INTERSECT : IT_OUTSIDE);
}
  
I hope someone could help me. Thanks alot... Mfg Impz0r PS. Could someone me explain how an Sphere --> Point intersection work?! Thanks in advance.
Stay Evil & Ugly!
Here''s some sphere-ray intersection code in java that works:

public float findIntersection(vector eye,vector pixel)
{
float a,b,c;
vector dir = vector.add(pixel,vector.mult(eye,-1));
a = dir.x*dir.x + dir.y*dir.y + dir.z*dir.z;
b = 2 * (dir.x*(eye.x - loc.x) + dir.y*(eye.y - loc.y) + dir.z*(eye.z - loc.z));
c = (eye.x - loc.x)*(eye.x - loc.x) + (eye.y - loc.y)*(eye.y - loc.y) + (eye.z - loc.z)*(eye.z - loc.z) - radius*radius;

float disc = b*b - 4 * a * c; //discriminant
if (disc < 0)
return -1;
else if(disc == 0)
{
float t;
t = -b / (2 * a);
if(t >= 1)
return t;
else return -1;
}
else
{
float t1,t2;
t1 = (-b + (float)Math.sqrt(disc)) / (2 * a);
t2 = (-b - (float)Math.sqrt(disc)) / (2 * a);
//System.out.println(t2 + " " + t1);
if(t2 >= geometry.EPSILON)
return t2;
if(t1 >= geometry.EPSILON)
return t1;
else
return -1;
}
//return closest t above 1
}

geometry.EPSILON is a small number really close to zero to allow for rounding errors, and the code returns -1 if there is no collision. Essentially, you take the equation of a sphere |r|=A (A being some length), and you have the parametric equation for a ray x = x0+ t*d (t=parameter, d=direction). From this, you can solve for what I have in the function. It boils down to the solution of a quadratic equation. You can see that this makes sense as any ray can intersect a sphere at 0,1 or 2 points, and a quadratic equation has 0,1 or 2 real solutions.
Advertisement
This is just a theory of mine that I haven't tried yet, but I'm pretty sure it would work.

With my method you must have these variables:
-Normal obtained from current triangle
-Center Point of sphere
-XYZ scale(used to determine the shape and size of the sphere)

For each triangle a ray will be created using the above three variables.

The steps you take:
-invert the normal and store result in a temp vector
-make the Center Point of the sphere the origin of the new ray
-multiply the temp vector with the XYZ scale, then add the result to the ray origin and store into the ray destination
-do a normal ray to triangle intersection test

Is this method common? If it is, is it the fastest?

[edited by - WhatEver on March 13, 2002 7:00:52 PM]
For a raytracer, the solving the quadratic is pretty darn fast. I don''t think anyone does a ray-triangle test. In fact, think it''s slower.
try this...

float ISectRaySphere (const CVector3& origin, const CVector3& dir, const CSphere& sphere)
{
CVector3 q;
VecSub (&q, sphere.GetCenter (), origin);
float c = q.Length ();
float v = Dot (q, dir);
float d = Sqr (sphere.GetRadius ()) - (Sqr (c) - Sqr (v));

// if no isect, return -1
if (d < 0.0f)
return (-1.0f);

// return the distance to the first isect pt
return (v - sqrt (d));
}
hi,
many thanks for your reply''s, i don''t wont code an raytracer btw, i would use it for collisions detection in may litle 3d engine

m_w_noname : i''ll try your solution soon ;D

Thanks alot...

Mfg Impz0r

PS: Did someone kown how i determinate intersection between a Sphere and a Plane?! Thanks in advance.
Stay Evil & Ugly!
Advertisement
Here's the point in sphere for ya(no slow square roots):


    bool PointInSphere(vector3f point, vector3f sphere_cen, float radius){   vector3f SpherePointPos;   float    DotLength;   //seudo: SpherePointPos=point-sphere_cen;   VectorSubtract3f(SpherePointPos, point, sphere_cen);   DotLength=VectorDot3f(SpherePointPos, SpherePointPos);   if(DotLength<=(radius*radius))   {      return true;   }   return false;}    


[edited by - WhatEver on March 14, 2002 6:08:56 PM]
Just for fun I made a sphere in sphere function for ya:


    bool SphereInSphere(vector3f center1, vector3f center2, float radius1, float radius2){   vector3f TestVector;   float    TestVectorDotLength;   VectorSubtract3f(TestVector, center1, center2);   TestVectorDotLength=VectorDot3f(TestVector, TestVector);   if(TestVectorDotLength<=((radius1+radius2)*(radius1+radius2)))   {      return true;   }   return false;}    


[edited by - WhatEver on March 14, 2002 7:20:45 PM]
inline const float CPlane::DistanceToPoint (const CVector3& pt) const
{
return (Dot (mNorm, pt) - mOffset);
}

uint32 CPlane::ClassifySphere (const CVector3& center, const float& radius, float *pDist) const
{
// calc the Sqr distance between plane normal & sphere center
// avoids the sqrrt
float distSqr = DistanceSqr (mNorm, center);
float radSqr = Sqr (radius);
if (distSqr < radSqr)
return INTERSECTS;
else if (distSqr >= radSqr)
return FRONT;
return BEHIND;
}


wow,

impressiv , WhatEver you code only for me this function *g*
many thanks.

Mfg Impz0r
Stay Evil & Ugly!

This topic is closed to new replies.

Advertisement