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);
}
Sphere --> Ray intersection?!
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:
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.
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.
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]
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));
}
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![](wink.gif)
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.
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
![](wink.gif)
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!
Here's the point in sphere for ya(no slow square roots):
[edited by - WhatEver on March 14, 2002 6:08:56 PM]
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:
[edited by - WhatEver on March 14, 2002 7:20:45 PM]
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;
}
{
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;
}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement