Skip to main content
gamedev.net
🔒 Locked

Ray Tracing

Started by ramsey 4 replies 1.1k views
Original Post
ramsey
ramsey
Hi, I'm trying to use ray tracing to detect whether a ray projected from some point intersects with a sphere. I have looked at many resources to get me started, this is the main one: http://www.codeproject.com/netcf/cfrt_article.asp This is how I calculate each of the points on the ray: To shoot a ray from origin to endpoint, it helps to think of it as linear movement (i.e. constant velocity) in time. I define the point at time t as: P(t) is the vector at time t P(0) is the vector at time 0, which is the starttime P(T) is the vector at time T, which is the endtime. V is the velocity vector V = (P(T)-P(0))/T P(t) = P(0)+V*t I want a fixed number of steps, so I set T to 1 and let t step from 0 to 1.0 (this simplifies the formula). By calculating the velocity from end point and startpoint there is no need for special cases (i.e. no need to worry about the direction of the ray, or whether it is going towards or away from the origin). Now, this works fine, what I'm actually having trouble with is the actual detection of intersection between the ray and the sphere. The problem is that it's only half working at the moment. I have spent many hours going through the code and can't see what's wrong. Here is a quick summary of what I'm doing: 1. Substitute the equation of the ray into the equation of the sphere 2. You end up with a quadratic equation which can be solved (via (-b +/- (b^2 - 4ac)^0.5)/(2a)) 3. If the discriminant (i.e. b^2 - 4ac) is negative then you know that there is no intersection between the ray and the sphere 4. Otherwise, the intersection points are the two solutions This approach is all taken from the URL link posted above (see the 'Sphere' section). Here is my code: ************************************************************** //calculate a, b & c for quadratic equation a = pow(x_velocity, 2) + pow(y_velocity, 2) + pow(z_velocity, 2); b = 2 * x_velocity * (x_begin - x_sphere) + 2 * y_velocity * (y_begin - y_sphere) + 2 * z_velocity * (z_begin - z_sphere); c = pow(x_sphere, 2) + pow(y_sphere, 2) + pow(z_sphere, 2) + pow(x_begin, 2) + pow(y_begin, 2) + pow(z_begin, 2) + 2*(-(x_sphere*x_velocity) -(y_sphere*y_velocity) -(z_sphere*z_velocity)) - pow(sphere_radius, 2); // check the value of the discriminator, if negative then there is no intersection if ( ( (pow(b, 2) - (4*a*c) ) >= 0.0) ) { //calculate the two intersection points t0 = (-b + pow(pow(b, 2) - (4*a*c), 0.5))/(2*a); t1 = (-b - pow(pow(b, 2) - (4*a*c), 0.5))/ (2*a); if (t0 < t1) clostest_intersection = t0; else closest_intersection = t1; // calculate the coordinates of the closest intersection point x_int = x_begin + x_velocity*intersection; y_int = y_begin + y_velocity*intersection; z_int = z_begin + z_velocity*intersection; } else printf("NO INTERSECTION\n"); ************************************************************** x,y,z_begin are the start coords of the ray. x,y,z_velocity is the velocity of the ray and equals x,y,z_end - x,y,z_begin. x,y,z_sphere are the coords of the sphere's centre. x,y,z_int is the closest intersection point (if any) Now, the above code works fine for a sphere that is positioned at the origin (with a ray starting at any point and ending at the origin, i.e. one that is travelling towards the sphere). It also works fine when the sphere has been translated to be at a position behind the starting point of the ray (i.e. the ray is travelling away from the sphere). Things seem to be going wrong when: 1. The sphere is positioned on the ray (e.g. half way along the ray). The algorithm doesn't pick up the intersection. 2. Positioned either side of the ray. Sometimes it considers this an intersection, others it doesn't (depends on the coords supplied). 3. Positioned a little ahead (but still in line with) of the ray end point. This is considered to be an intersection. I know that I have correctly applied the formulae manipulation because I've done a few test ones by hand and then compared it to the values of t0 and t1 produced in my code. I suspect that the problem is to do with the fact that I am translating the sphere to different positions, but I thought that the above algorithm should work for all sphere positions? Can anyone spot what is going wrong with my code? Thanks, Ramsey
Nice Coder
Nice Coder
I'm not too good at math (i haven't even done quadratics before...)
So i can't help you, sorry. :(

But a few things from this forum.

1. use < a href = " url here " >Text link here < / a > Please remove the spaces in the tags to get it to work.

2. use [ code ] and [ source ] tags.

Also, what does this do?
pow(pow(b, 2) - (4*a*c), 0.5))

Shouldn't it just be
sqrt((b * b) - (4 * a * c)) ? (powers are very very slow, and you might get some errors from doing it your way which are hard to track down).

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
MJAY
MJAY
Hi, however i see that your solution ( formula solving ) is a good way for generalization. So you may use it for lots of things.

If you need immediately, you may try a quick dirty hack :) by finding the distance from the origin of sphere to the line. if it's equals or smaller than the distance of spheres outer part to origin, then it hits the sphere..
Dmytry
Dmytry
i'm posting it for about seventh time.
//// Ray-sphere intersection. // p=(ray origin position - sphere position),// d=ray direction,// r=sphere radius,// Output:// i1=first intersection distance,// i2=second intersection distance// i1<=i2// i1>=0// returns true if intersection found,false otherwise.// bool RaySphereIntersect(const Vec3d &p, const Vec3d &d, double r, double  &i1, double &i2){	double det,b;	b = -DotProd(p,d);	det=(b*b) - (p.x*p.x + p.y*p.y + p.z*p.z) + r*r;	if (det<0){		return false;	}	det= sqrt(det);	i1= b - det;	i2= b + det;	// intersecting with ray?	if(i2<0) return false;	if(i1<0)i1=0;	return true;};

It's basically quadratic, just rearranged, optimized a bit, and cleared.
ramsey
ramsey
Okay, managed to fix it. I changed the calculation for c to the following:

c = pow(x_begin - x_sphere,2) + pow(y_begin -
y_sphere,2) + pow(z_begin - z_sphere,2) -
pow(sphere_radius,2);

It now properly detects whether or not there is intersection with the sphere, regardless of where the sphere is positioned. The only remaining concern is that it still counts a sphere placed ahead of, and in line with, the ray end point as being an intersection. No idea why...
Zakwayda
Zakwayda
Quote:
It now properly detects whether or not there is intersection with the sphere, regardless of where the sphere is positioned. The only remaining concern is that it still counts a sphere placed ahead of, and in line with, the ray end point as being an intersection. No idea why...
You say ray endpoint - does that mean you want the ray to have finite length (i.e. a segment)? In that case, you'll have to catch the case where the parametric point of intersection is greater than whatever upper limit you've set, and return false. It doesn't look like you were doing that in your original code, but I may be misunderstanding what you're asking...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.