CC BY 4.0 (除特别声明或转载文章外)
如果这篇博客帮助到你,可以请我喝一杯咖啡~
作业6介绍加速结构
求BVH
是前面几天前写的代码,但是今天才写笔记。
这几天实验室网线没网。自己拖了,然后也耽搁了。
凭着自己的理解,然后看看网上人家的代码的思路。
首先是修改作业5的一个函数
inline Intersection Triangle::getIntersection(Ray ray)
{
Intersection inter;
if (dotProduct(ray.direction, normal) > 0)
return inter;
double u, v, t_tmp = 0;
Vector3f pvec = crossProduct(ray.direction, e2);
double det = dotProduct(e1, pvec);
if (fabs(det) < EPSILON)
return inter;
double det_inv = 1. / det;
Vector3f tvec = ray.origin - v0;
u = dotProduct(tvec, pvec) * det_inv;
if (u < 0 || u > 1)
return inter;
Vector3f qvec = crossProduct(tvec, e1);
v = dotProduct(ray.direction, qvec) * det_inv;
if (v < 0 || u + v > 1)
return inter;
t_tmp = dotProduct(e2, qvec) * det_inv;
// TODO find ray triangle intersection
//和作业5差不多,需要讲一些值赋给Intersection。
if(t_tmp>EPSILON&&u>EPSILON&&v>EPSILON&&1-u-v>EPSILON) {
inter.happened = true;
inter.coords = ray.origin+t_tmp*ray.direction;
inter.normal = normal;
inter.distance = t_tmp;
inter.obj = this;
inter.m = m;
}
return inter;
}
判断与包围盒是否相交
inline bool Bounds3::IntersectP(const Ray& ray, const Vector3f& invDir,
const std::array<int, 3>& dirIsNeg) const
{
// invDir: ray direction(x,y,z), invDir=(1.0/x,1.0/y,1.0/z), use this because Multiply is faster that Division,光线,光线方向的倒数,光线的方向是否是反的
// dirIsNeg: ray direction(x,y,z), dirIsNeg=[int(x>0),int(y>0),int(z>0)], use this to simplify your logic
// TODO test if ray bound intersects就是求每个面的进入时间、离开时间,然后进入时间取最大,离开时间取最小,然后判断,课上讲过,知道参数代表的意义,容易写出来。
float t_mi_x = (pMin.x-ray.origin.x)*invDir[0];
float t_mi_y = (pMin.y-ray.origin.y)*invDir[1];
float t_mi_z = (pMin.z-ray.origin.z)*invDir[2];
float t_ma_x = (pMax.x-ray.origin.x)*invDir[0];
float t_ma_y = (pMax.y-ray.origin.y)*invDir[1];
float t_ma_z = (pMax.z-ray.origin.z)*invDir[2];
if(!dirIsNeg[0]) {
float tmp = t_mi_x;
t_mi_x = t_ma_x;
t_ma_x = tmp;
}
if(!dirIsNeg[1]) {
float tmp = t_mi_y;
t_mi_y = t_ma_y;
t_ma_y = tmp;
}
if(!dirIsNeg[2]) {
float tmp = t_mi_z;
t_mi_z = t_ma_z;
t_ma_z = tmp;
}
float t_enter = fmax(t_mi_x,fmax(t_mi_y,t_mi_z));
float t_exit = fmin(t_ma_x,fmin(t_ma_y,t_ma_z));
if(t_enter<=t_exit&&t_exit>=0) return true;
return false;
}
BVH加速求交
Intersection BVHAccel::getIntersection(BVHBuildNode* node, const Ray& ray) const
{
// TODO Traverse the BVH to find intersection
// 首先是个递归的过程,还是先要把光线方向的正反求出来。然后
// 如果这个节点和光线不相交,直接返回
// 如果这个节点是叶子节点,那么直接计算和这个节点的物体的相交。
// 然后分别求左儿子右儿子的相交,返回距离小的一个,因为光线先打到距离小的那个嘛。
std::array<int,3> dirIsNeg;
dirIsNeg[0] = (ray.direction[0]>0);
dirIsNeg[1] = (ray.direction[1]>0);
dirIsNeg[2] = (ray.direction[2]>0);
Intersection inter;
if(!node->bounds.IntersectP(ray,ray.direction_inv,dirIsNeg)) {
return inter;
}
if(node->left==nullptr&&node->right==nullptr) {
return node->object->getIntersection(ray);
}
Intersection lson = getIntersection(node->left,ray);
Intersection rson = getIntersection(node->right,ray);
if(lson.distance<rson.distance) return lson;
else return rson;
}