In this I am considering that box is axis aligned as shown in figure:
Axis Aligned means all the faces of box (box has 6 faces) lie along or parallel to the x axis or y axis or z axis.
Algorithm: Set tnear = -INFINITY , tfar = +INFINITY Get near point and far point from the cube For the pair of all planes there are 3 planes this algorithm is for x plane if rays x Direction (xd) = 0, the ray is parallel to the planes so: if x0 < x near point or x0 > x far point return FALSE else the ray is not parallel to the planes, so calculate intersection distances of planes t1 = (xl - x0) / xd t2 = (xh - x0) / xd if t1 > t2 , swap t1 and t2 if t1 > tnear , set tnear = t1 if t2 < tfar , set tfar = t2 if tnear > tfar , box is missed so return FALSE if tfar < 0 , box is behind ray so return FALSE Repeat procedure for y, then z All tests were survived, return TRUE or tnear value
Explanation of algorithm: 1. Find the near and far points of the box 2. Now perform whether the ray is hitting the box or not. This can be done by checking ray direction x coordinate is less than near points x coordinate and grater than x coordinate of far point. If this condition is true means ray is not hitting the planes 3. Else find where the ray is hitting the surface 4. Based on intersection return true or false. I used to return tnear when there is intersection otherwise -1
In C++: float Cube::intersectCube(SbVec3f rayDirection,SbVec3f rayStart){ float t1,t2,tnear = -1000.0f,tfar = 1000.0f,temp,tCube; SbVec3f b1 = getNearPoint(); SbVec3f b2 = getFarPoint(); bool intersectFlag = true; for(int i =0 ;i < 3; i++){ if(rayDirection[i] == 0){ if(rayStart[i] < b1[i] || rayStart[i] > b2[i]) intersectFlag = false; } else{ t1 = (b1[i] - rayStart[i])/rayDirection[i]; t2 = (b2[i] - rayStart[i])/rayDirection[i]; if(t1 > t2){ temp = t1; t1 = t2; t2 = temp; } if(t1 > tnear) tnear = t1; if(t2 < tfar) tfar = t2; if(tnear > tfar) intersectFlag = false; if(tfar < 0) intersectFlag = false; } } if(intersectFlag == false) tCube = -1; else tCube = tnear; return tCube; }
Normal Calculation for Cube: Cocept: We know there are 6 faces for cube. The near point is on three planes and so the far point. Now check the intersection point lies on which face, this can be easily done by calculating distance between intersection point x,y,z coordinates and near point x,y,z coordinates if the distance is less or equivalent to epsilon value then that intersection point lie on -x or -y or -z and if the intersection point is near to far point then intersection point lie on +x or +y or +z.
Note: This planes can be interchanged between far and near point based on the your image setup
Code: float EPSI = 0.01; if(abs(point[0] - cubes[locCube].getNearPoint()[0]) < EPS) normal.setValue(-1,0,0); else if(abs(point[0] - cubes[locCube].getFarPoint()[0]) < EPS) normal.setValue(1,0,0); else if(abs(point[1] - cubes[locCube].getNearPoint()[1]) < EPS) normal.setValue(0,-1,0); else if(abs(point[1] - cubes[locCube].getFarPoint()[1]) < EPS) normal.setValue(0,1,0); else if(abs(point[2] - cubes[locCube].getNearPoint()[2]) < EPS) normal.setValue(0,0,-1); else if(abs(point[2] - cubes[locCube].getFarPoint()[2]) < EPS) normal.setValue(0,0,1); where locCube: cube number with which we are caculating normal EPS: epsilon value
Hello, now I'm do ray tracing engine and your post be very useful for me. thank you. I think you intersection function be more laconic if do small correction
ReplyDeletefloat Cube::intersectCube(SbVec3f rayDirection,SbVec3f rayStart){
float t1,t2,tnear = -1000.0f,tfar = 1000.0f,temp,tCube;
SbVec3f b1 = getNearPoint();
SbVec3f b2 = getFarPoint();
for(int i =0 ;i < 3; i++){
if(rayDirection[i] == 0){
if(rayStart[i] < b1[i] || rayStart[i] > b2[i])
return -1;
}
else{
t1 = (b1[i] - rayStart[i])/rayDirection[i];
t2 = (b2[i] - rayStart[i])/rayDirection[i];
if(t1 > t2){
temp = t1;
t1 = t2;
t2 = temp;
}
if(t1 > tnear)
tnear = t1;
if(t2 < tfar)
tfar = t2;
if(tnear > tfar || tfar < 0)
return -1;
}
}
return tnear;
}