|
In this section, vectors are expressed in bold while points are not.
A line is defined by two points; it is infinite in length passing through the points and extending forever in both directions.
A line segment ( segment for short ) is defined by two endpoints.
A ray is semi-infinite; it is specified by a point and a direction.
So, a line, a segment, and a ray all consist of points; in our notation, they should not be bold. ( Recall the homogeneous coordinate representation and affine combination of points. ) We use a parameter t to describe them ( parametric representation ).
Suppose P1 and P2 are two points defining a line L(t). Let b = P2 - P1. Then
| segment: | 0 ≤ t ≤ 1 | |
| ray: | 0 ≤ t ≤ ∞ | |
| line: | -∞ < t < ∞ |
class Ray
{
private:
Point3 origin; //starting point
Vector3 direction; //vector
public:
Ray() : origin( Point3( 0, 0, 0 ) ), direction( Vector3( 0, 1, 0 ) ) {};
Ray( Point3& an_origin, Vector3& a_direction );
....
};
|
As mentioned above, a ray is specified by its starting position O and a unit vector D and can be ragarded as a set of points given by
| L = O + tD   0 ≤ t < ∞ |
|
A plane is specified by a normal vector N perpendicular to the plane:
|
( P - P' ) ⋅ N = 0
implies that (x - x')Nx + (y - y')Ny + (z - z')Nz = 0 or ax + by + cz + d = 0 |
|
Suppose P is the intersection of the line and the plane. Then
Solving for t, we have
( P' - O )⋅N
t = ---------------
D⋅N
|
|
( P1' - O)⋅N
t1 = ---------------
D⋅N
|
( P2' - O )⋅N
t2 = ---------------
D⋅N
|
n = N / |N| d = n ⋅(v0 - O) is the distance from the origin to the plane if n is normalized |
|
|
Barycentric Coordinates
Si, i = 1, 2, 3 are proportional to the areas of the corresponding subtriangles and If the area of the triangle is normalized to 1, so that Si becomes the area of the actual subtriangle, we have homogeneous Barycentric coordinates ( S1, S2, S3 ) are referred to as Barycentric coordinates of P Criteria for inside triangle:
So, if we know the barycentric coordinates of the hit point, we can accept or reject the ray with very simple tests: Point P is outside the triangle if one of the barycentric coordinates Si is smaller than zero |
|
Area of a polygon is
| n-1 | ||
| A = ½ | ![]() |
xi yi+1 - xi+1 yi |
| i=0 |
Suppose vertices P1, P2 and P3 form the triangle and ( α, β, γ ) are barycentric coordinates of point P:
Substituting with α = 1 - β - γ, we have
It is easier to solve if we project this in a 2D plane. ( Projecting both the triangle and the hit-point P onto another plane does not change the barycentric coordinates of P. After projection, all computations can be performed more efficiently in 2D. For example, we can project them into the XY plane. If we let c = (P2 - P1) , b = (P3 - P1), and h = P - P1. , we can rewrite (1) as
When projected onto the XY plane, we obtain the equations,
βcy + γby = hy
bxhy - byhx β = ------------ bxcy - bycx |
hxcy - hycx γ = ------------ bxcy - bycx |
bool intersect_ray_triangle ( const Triangle triangle, Ray &ray, double &t )
{
Vec3 v01 = triangle.p1 - triangle.p0;
Vec3 v02 = triangle.p2 - triangle.p0;
Vec3 normal = v01 ^ v02; //normal to triangle
Plane plane ( triangle.p0, normal ); //plane containing triangle
bool hit_plane = intersect_ray_plane ( plane, ray, t );
if ( !hit_plane ) return false;
Point3 q = ray.getPoint( t );
//check if q is inside triangle
double bx, by, cx, cy, hx, hy;
double beta, gamma;
Vec3 b, c, h;
c = v01;
b = v02;
h = q - triangle.p0;
//find the dominant axis
char axis;
if ( fabs ( normal.x ) > fabs ( normal.y ) )
if ( fabs ( normal.x ) > fabs ( normal.z ) )
axis = 'x';
else
axis = 'z';
else
if ( fabs ( normal.y ) > fabs ( normal.z ) )
axis = 'y';
else
axis = 'z';
switch ( axis ) {
case 'x': //project on YZ plane
bx = b.y; by = b.z;
cx = c.y; cy = c.z;
hx = h.y; hy = h.z;
break;
case 'y': //project on ZX plane
bx = b.z; by = b.x;
cx = c.z; cy = c.x;
hx = h.z; hy = h.x;
break;
case 'z': //project on XY plane
bx = b.x; by = b.y;
cx = c.x; cy = c.y;
hx = h.x; hy = h.y;
break;
}
double denominator = bx * cy - by * cx;
beta = ( bx * hy - by * hx ) / denominator;
gamma = ( hx * cy - hy * cx ) / denominator;
if ( beta < 0 ) return false;
if ( gamma < 0 ) return false;
if ( beta + gamma > 1 ) return false;
return true;
}
|
We may preprocess some values to speed up the process.
|
|
If s = 1, it becomes the generic cylinder; if s = 0, it becomes the generic cone.

e.g. spheres, cylinders, ellipsoids, paraboloids, hyperboloids, cones
void buildkdtree( Node* node )
{
if (stopcriterionmet()) return
splitpos = findoptimalsplitposition()
leftnode = new Node()
rightnode = new Node()
for (all primitives in node)
{
if (node->intersectleftnode()) leftnode->addprimitive( primitive )
if (node->intersectrightnode()) rightnode->addprimitive( primitive )
}
buildkdtree( leftnode )
buildkdtree( rightnode )
}
|
G becomes a leaf as it is convex