Sunday, March 28, 2010

PostTwiceDaily2 03/28/2010 (p.m.)

  • tags: no_tag

    • Color trace_ray( Ray original_ray )

      {

        Color point_color, reflect_color, refract_color

        Object obj




        obj = get_first_intersection( original_ray )


        point_color = get_point_color( obj )



        if ( object is reflective )

          reflect_color = trace_ray( get_reflected_ray( original_ray, obj ) )

        if ( object is refractive )

          refract_color = trace_ray( get_refracted_ray( original_ray, obj ) )



        return ( combine_colors( point_color, reflect_color, refract_color ))


      }
  • tags: no_tag

    • Ray/Segment-Triangle Intersection


      Consider a ray R (or a segment S) from
      P0 to P1,
      and a triangle T with vertices V0,
      V1 and V2
      The triangle T lies in the plane p
      through V0 with normal vector
      n = (V1-V0)×(V2-V0). 
      To get the intersection of R (or S) and T, one first
      determines the intersection of R (or S) and
      p
      .  If they do not
      intersect, then the ray (or segment) also does not intersect T and we are
      done.  However, if they intersect in the point PI=P(rI),
      we need to determine if this point is in the triangle T for there to be a
      valid intersection.


      There are a number of ways to test for the
      inclusion of a point inside a 3D planar triangle.  The algorithms given by
      [
      Badouel, 1990] and [O'Rourke, 1998] project the
      point and triangle onto a 2D coordinate plane where inclusion is tested. 
      To implement these algorithms, one must choose a projection coordinate plane
      which avoids a degenerate projection.  This is done by excluding the
      coordinate which has the largest component in the plane normal vector n [Synder
      & Barr, 1987].  The intent is to reduce the 3D problem to a simpler 2D
      problem which has an efficient solution.  However, there is a small
      overhead involved in selecting and applying the projection function.  The
      algorithm of
      [Moller-Trumbore, 1997] (MT) does not project into 2D, and
      finds a solution using direct 3D computations.  Testing with some complex
      models shows that the MT algorithm is faster than the one by Badouel.



      We present an alternate method which also uses direct 3D computations to
      determine inclusion, avoiding projection onto a 2D coordinate plane.  As a
      result, the code is cleaner and more compact.  Like
      [Moller-Trumbore,
      1997], we use the parametric equation of
      p
      relative
      to T, but derive a different method of solution which computes the
      parametric
      coordinates of the intersection point in the
      plane.  The parametric plane equation (see:
      Planes
      in Algorithm
      4) is given by:



      where s and t are real
      numbers, and u =
      (V1-V0)
      and v = (V2-V0)
      are edge vectors of T.  A point P = V(s,t)
      is in the triangle T when
      s>=0, t>=0, and
      s+t<=1.  So, given PI, one
      just has to find the (sI,tI)-coordinate for
      it, and then check these inequalities to verify inclusion in T.  Further,
      a point P = V(s,t) is on an edge of T if one of the conditions
      s
      =0, t=0, or s+t=1 is true (each condition corresponds
      to one edge).  Also, the three vertices are given by: V0=V(0,0),
      V1=V(1,0), and V2=V(0,1).



      To solve for sI and tI,
      we define a 3D generalization of Hill's "perp-dot" product
      [Hill, 1994].  For an embedded 2D plane

      p
      with a
      normal vector n, and any vector a in the plane (that is, a
      satisfies n·a = 0), define the "generalized perp operator
      on
      p"
      by: a^ = n×a
      Then, a^ is another
      vector in the plane
      p
      (since n·a^ = 0),
      and it is perpendicular to a (since a·a^
      = 0).  Further, this perp operator is linear on vectors in
      p;
      that is, (Aa + Bb)^
      = Aa^ + Bb^
      where a and b are vectors in

      p
      , and A
      and B are scalars.  Note that if

      p
      is the 2D
      xy-plane (z=0) with n = (0,0,1), then this is exactly the
      same 2D perp operator given by [Hill, 1994].


      We can now use this generalized perp
      operator to solve the plane's parametric equation for the intersection point PI
      Put w = (PI-V0) which is
      another vector in
      p
      Then, we want to solve the equation: w = su + tv
      for s and t.  Take the dot product of both sides with v^
      to get: w · v^ =
      s
      u · v^ + tv
      · v
      ^
      = su · v^,
      and solve for sI.
        Similarly, taking the dot
      product with u^,
      we get: w · u^
      = su · u^ +
      t
      v · u^
      = tv · u^,
      and solve for tI.  We get:








      and




      The denominators are nonzero whenever the triangle T is
      nondegenerate (that is, has a nonzero area).  When T is degenerate,
      it is either a segment or a point, and in either case does not uniquely define a
      plane and the computed normal vector is (0,0,0).  So, this case must be
      treated separately as a 3D segment-segment intersection which was treated in Algorithm
      5 (see: Lines and Segments).


      Altogether we have used 3 cross products which is a lot of
      computation.  However, for any three vectors a b c, the following
      identity holds for left association of the cross product:  (a × b)
      × c = (a · c) b - (b · c) a
      [Note: the cross product is not associative, and so there is a different (but
      similar) identity for right association].  Applying the left association
      identity results in the simplifications:



      And we can now compute sI
      and tI using only dot products
      as:




      with 5 distinct dot products.  We have arranged terms so
      that the two denominators are the same and only need to be calculated once.

    • // Assume that classes are
      already given for the objects:

      //    Point and Vector with

      //        coordinates {float x, y, z;}

      //        operators for:

      //            == to test
      equality

      //            != to test
      inequality

      //            (Vector)0 =
      (0,0,0)         (null vector)

      //            Point 
      = Point ± Vector

      //            Vector =
      Point - Point

      //            Vector =
      Scalar * Vector    (scalar product)

      //            Vector =
      Vector * Vector    (cross product)

      //    Line and Ray and Segment with defining
      points {Point P0, P1;}

      //        (a Line is infinite, Rays and
      Segments start at P0)

      //        (a Ray extends beyond P1, but a
      Segment ends at P1)

      //    Plane with a point and a normal {Point V0; Vector
      n;}

      //    Triangle with defining vertices {Point V0, V1, V2;}

      //    Polyline and Polygon with n vertices {int n;
      Point *V;}

      //        (a Polygon has V[n]=V[0])

      //===================================================================


      #define SMALL_NUM 
      0.00000001 // anything that avoids division overflow

      // dot product (3D) which allows vector operations in arguments

      #define dot(u,v)   ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z)


      //
      intersect_RayTriangle(): intersect a ray with a 3D triangle

      //    Input:  a ray R, and a triangle T

      //    Output: *I = intersection point (when it exists)

      //    Return: -1 = triangle is degenerate (a segment or point)

      //             0 =
      disjoint (no intersect)

      //             1 =
      intersect in unique point I1

      //             2 =
      are in the same plane

      int

      intersect_RayTriangle( Ray R, Triangle T, Point* I )

      {

          Vector    u, v, n;            
      // triangle vectors

          Vector    dir, w0, w;         
      // ray vectors

          float     r, a, b;            
      // params to calc ray-plane intersect



          // get triangle edge vectors and plane normal

          u = T.V1 - T.V0;

          v = T.V2 - T.V0;

          n = u * v;            
      // cross product

          if (n == (Vector)0)           
      // triangle is degenerate

              return -1;                
      // do not deal with this case



          dir = R.P1 - R.P0;            
      // ray direction vector

          w0 = R.P0 - T.V0;

          a = -dot(n,w0);

          b = dot(n,dir);

          if (fabs(b) < SMALL_NUM) {     // ray is
      parallel to triangle plane

              if (a == 0)               
      // ray lies in triangle plane

                  return 2;

              else return 0;            
      // ray disjoint from plane

          }



          // get intersect point of ray with triangle plane

          r = a / b;

          if (r < 0.0)                  
      // ray goes away from triangle

              return 0;                 
      // => no intersect

          // for a segment, also test if (r > 1.0) => no intersect



          *I = R.P0 + r * dir;          
      // intersect point of ray and plane



          // is I inside T?

          float    uu, uv, vv, wu, wv, D;

          uu = dot(u,u);

          uv = dot(u,v);

          vv = dot(v,v);

          w = *I - T.V0;

          wu = dot(w,u);

          wv = dot(w,v);

          D = uv * uv - uu * vv;



          // get and test parametric coords

          float s, t;

          s = (uv * wv - vv * wu) / D;

          if (s < 0.0 || s > 1.0)       
      // I is outside T

              return 0;

          t = (uv * wu - uu * wv) / D;

          if (t < 0.0 || (s + t) > 1.0)  // I is outside T

              return 0;



          return 1;                     
      // I is in T

      }


Posted from Diigo. The rest of my favorite links are here.