Advertisement

Triangle-ray intersection (doing it quick)

Started by June 18, 2002 10:26 AM
1 comment, last by stefu 22 years, 8 months ago
hi! To solve triangle-ray intersection I need: vec3 ray_start,ray_vector; // is ray (or line segment) vec3 v1,v2,v3; // are triangle corners From there i get: v1 + r*(v2-v1) + s*(v3-v1) = ray_start + t*ray_vector There I need to solve r,s and t. I need to know all r,s and t for my collision system (I think so ). If 0<=r,s,r+s,t<=1 then I know that my ray intersects triangle (I think so ). To solve it? That's little problem. How to do it fast? (Of course I use octree or similar tree too speed it up) I got this: vec3 p = ray_start; vec3 d = -ray_vector; vec3 s2 = v2-v1; vec3 s3 = v3-v1; vec3 o = p-v1; So the same equitation is simpler: r*s2 + s*s3 + t*d = o Then I get: r*s2.x + s*s3.x + t*d.x = o.x r*s2.y + s*s3.y + t*d.y = o.y r*s2.z + s*s3.z + t*d.z = o.z That is:

| s2.x s3.x d.x |   | r |   | o.x |
| s2.y s3.y d.y | X | s | = | o.y |
| s2.z s3.z d.z |   | t |   | o.z |
  
Shorter: M X T = O Solving: T = (M^) X O // where M^ is inverted M Right? But I don't think matrix inversion is very effective here, what do you think? Is it? Another way is to take pen and paper and start combining opening those equitations. First solve for example t, then s and finally r. I'm afraid I'll go wrong somewhere. Maybe I try it. The good point is that when I have solved t I can stop doing more work if is t<0 or t>1. Is this the way to do it quick, really quick? I have only found tuts that show how to do it slow Using plane, you know Don't know why I aactually wrote this If anyone can help somewhere? I don't think using matrix here is good. In any case I'll take pen and paper and start solwing it progressively. Maybe I'll tell something if I get somthing working bye! [edited by - stefu on June 18, 2002 5:34:30 PM]
hi!

Now I have solution (not yet tested )

r*s2.x + s*s3.x + t*d.x = o.xr*s2.y + s*s3.y + t*d.y = o.yr*s2.z + s*s3.z + t*d.z = o.zrewrite those above (for cleaner look):r*x1 + s*x2 + t*x3 = x4r*y1 + s*y2 + t*y3 = y4r*z1 + s*z2 + t*z3 = z4I solved t, s and r. Each can be calculated in three different ways (select one that doest case div by zero).float t1 = ((z4*x1-x4*z1)*(y2*x1-x2*y1)-(y4*x1-x4*y1)*(z2*x1-x2*z1)) /	           ((x3*y1-y3*x1)*(z2*x1-x2*z1)-(x3*z1-z3*x1)*(y2*x1-x2*y1));float t2 = ((z4*y1-y4*z1)*(y2*x1-x2*y1)-(y4*x1-x4*y1)*(z2*y1-y2*z1)) /	           ((x3*y1-y3*x1)*(z2*y1-y2*z1)-(y3*z1-z3*y1)*(y2*x1-x2*y1));float t3 = ((z4*y1-y4*z1)*(z2*x1-x2*z1)-(z4*x1-x4*z1)*(z2*y1-y2*z1)) /	           ((x3*z1-z3*x1)*(z2*y1-y2*z1)-(y3*z1-z3*y1)*(z2*x1-x2*z1));if( t<0 || t>1 ) return;float s1 = ((y4*x1-x4*y1)+t*(x3*y1-y3*x1))/(y2*x1-x2*y1);float s2 = ((z4*x1-x4*z1)+t*(x3*z1-z3*x1))/(z2*x1-x2*z1);float s3 = ((z4*y1-y4*z1)+t*(y3*z1-z3*y1))/(z2*y1-y2*z1);if( s<0 || s>1 ) return;float r1 = (x4-s*x2-t*x3)/x1;float r2 = (y4-s*y2-t*y3)/y1;float r3 = (z4-s*z2-t*z3)/z1;if( r<0 || r>1 || r+s>1 ) return;Now if we get here means that the ray intersects triangle.We also have the (texture) coordinate (r,s) in triangle space Collision point is easily:ray_start + t*ray_vector;And distance from ray_start to collision pos is as easy.It's the length of t*ray_vector.Right? 


Now need to try it in practise

I hope this works

I wrote it here in case someone is interested since I haven't found this (trivial) solution yet elsewhere.
Again, not yet tested. I'll tell tomorrow if it worked

There are zillion multiplications, maybe they can be optimized a little


bye!

[edited by - stefu on June 18, 2002 5:44:45 PM]
Advertisement
I admit I was lazy and didn't read your post fully, but I do know how to do triangle-ray intersection. It's actually quite simple.

First create a plane out of the triangle. You have the three points, so we can determine the normal by doing the crossproduct between two of the points. Let's assume that these points are in counter-clockwise order:
                     . v1            . .           .   .          .      .       v2..........v3    

Yay for shoddy ASCII art!


  Normal = CrossProduct(v2 - v1, v3 - v1);Normalize(Normal);// D = DistanceD = DotProduct(Normal, v1);  // or v2 or v3, doesn't matter as long as it's on the triangle     


We then do a ray-plane intersection to find the point where the ray hits the triangle's plane:


  // I'll skip a lot of testing here.  What you first want to do// is check and see if the ray passes through the plane at all, // which is checked by making sure the DotProducts of the start// and end points of the ray are opposite signsfloat Sum = 0.0f;float D_Start;Sum += (D_Start = fabs(DotProduct(Normal, ray_start) - D));Sum += fabs(DotProduct(Normal, ray_start + ray_vector) - D);vec3 intersection = ray_start + (ray_vector * (D_Start / Sum));// Little explanation.  We have the ray we are shooting.  We get // the dot products of the start and end points and add the // absolute value.  Picture a triangle perpendicular to the// triangle plane.  The ray vector is the hypotenuse, and the// dot product sum is one of the legs.  Similar triangles // indictate that we can multiply the hypotenuse by the ratio// of the two legs to get the intersection point.  


And finally, three half-plane checks (hope I'm using correct terminology ) to check if it's inside the triangle.

[edited by - Zipster on June 18, 2002 5:48:20 PM]

[edited by - Zipster on June 18, 2002 5:48:57 PM]

[edited by - Zipster on June 18, 2002 5:51:24 PM]

This topic is closed to new replies.

Advertisement