六个面拼接起来,没什么值得一提的。
我在这里做了一点小小的改进:在内部做了一个BVH结构,实测能快一倍
class box : public hitable {
public:
box() {}
box(const vec3& p0, const vec3& p1, shared_ptr<material> ptr);
virtual bool hit(const ray& r, double t_min, double t_max, record& rec) const override;
virtual bool bounding_box(AABB& output_box) const override {
bvh.bounding_box(output_box);
return true;
}
public:
vec3 box_min;
vec3 box_max;
bvh_node bvh;
};
inline box::box(const vec3& p0, const vec3& p1, shared_ptr<material> ptr) {
box_min = p0;
box_max = p1;
hitable_list sides;
sides.add(make_shared<xy_rect>(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr));
sides.add(make_shared<xy_rect>(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr));
sides.add(make_shared<xz_rect>(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr));
sides.add(make_shared<xz_rect>(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr));
sides.add(make_shared<yz_rect>(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr));
sides.add(make_shared<yz_rect>(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr));
bvh = bvh_node(sides);
}
inline bool box::hit(const ray& r, double t_min, double t_max, record& rec) const {
return bvh.hit(r, t_min, t_max, rec);
}
在光追器中,让一个物体位移不一定真的需要修改物体的坐标,改变光的位置也可以!
把光的起点加上一个负的位移分量,计算相交,然后把交点再加回位移分量就行了
class translate : public hitable {
public:
translate(std::shared_ptr<hitable> &p, const vec3 &displacement)
: tar(p), offset(displacement) {}
bool bounding_box(AABB &box_out) const override;
bool hit(const ray &r, double t_min, double t_max,
record &rec) const override;
private:
std::shared_ptr<hitable> tar;
vec3 offset;
};
inline bool translate::hit(const ray &r, double t_min, double t_max,
record &rec) const {
ray ray_moved(r.origin() - offset, r.dir);
if (!tar->hit(ray_moved, t_min, t_max, rec)) {
return false;
}
rec.p = rec.p + offset;
set_face_normal(ray_moved, rec.normal, rec);
return true;
}
inline bool translate::bounding_box(AABB &box_out) const {
if (!tar->bounding_box(box_out))
return false;
box_out = AABB(box_out.min() + offset, box_out.max() + offset);
return true;
}
和上面的思路大致相同
先把起点转过去,再把方向转一转,最后把交点转回来.........
本质上就是个旋转矩阵
class rotate_y : public hitable{
public:
rotate_y(shared_ptr<hitable> p, double angle);
virtual bool hit(
const ray& r, double t_min, double t_max, record& rec) const override;
virtual bool bounding_box(AABB& output_box) const override {
output_box = bbox;
return hasbox;
}
public:
shared_ptr<hitable> ptr;
double sin_theta;
double cos_theta;
bool hasbox;
AABB bbox;
};
inline rotate_y::rotate_y(shared_ptr<hitable> p, double angle) : ptr(p) {
auto radians = d2radian(angle);
sin_theta = sin(radians);
cos_theta = cos(radians);
hasbox = ptr->bounding_box(bbox);
vec3 min( Infinity, Infinity, Infinity);
vec3 max(-Infinity, -Infinity, -Infinity);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
auto x = i*bbox.max().x() + (1-i)*bbox.min().x();
auto y = j*bbox.max().y() + (1-j)*bbox.min().y();
auto z = k*bbox.max().z() + (1-k)*bbox.min().z();
auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
vec3 tester(newx, y, newz);
for (int c = 0; c < 3; c++) {
min[c] = fmin(min[c], tester[c]);
max[c] = fmax(max[c], tester[c]);
}
}
}
}
bbox = AABB(min, max);
}
inline bool rotate_y::hit(const ray& r, double t_min, double t_max, record& rec) const {
auto origin = r.origin();
auto direction = r.direction();
origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2];
origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2];
direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2];
direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2];
ray rotated_r(origin, direction);
if (!ptr->hit(rotated_r, t_min, t_max, rec))
return false;
auto p = rec.p;
auto normal = rec.normal;
p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2];
p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2];
normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2];
normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2];
rec.p = p;
set_face_normal(rotated_r, normal,rec);
return true;
}
#结果
这章节怎么说呢.....
有点扯淡,每次旋转的计算量大上天了,真不如直接把点进行位移
我猜测可能是因为作者觉得这只是本入门书籍所以没写这么多吧,毕竟模型变换一讲就是一大章节。
后续我会把我在魔改rayTracer里做的那个变换系统移植过来,大概...在这本书做完之后8