Implement instance rotation
This commit is contained in:
74
hittable.h
74
hittable.h
@@ -64,4 +64,78 @@ class translate : public hittable {
|
||||
aabb bBox;
|
||||
};
|
||||
|
||||
class rotateY : public hittable {
|
||||
public:
|
||||
rotateY(shared_ptr<hittable> object, double angle) : object(object) {
|
||||
auto radians = degreesToRadians(angle);
|
||||
sinTheta = sin(radians);
|
||||
cosTheta = cos(radians);
|
||||
bBox = object->boundingBox();
|
||||
|
||||
point3 min(infinity, infinity, infinity);
|
||||
point3 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.x.max + (1 - i) * bBox.x.min;
|
||||
auto y = j * bBox.y.max + (1 - j) * bBox.y.min;
|
||||
auto z = k * bBox.z.max + (1 - k) * bBox.z.min;
|
||||
|
||||
auto newX = cosTheta * x + sinTheta * z;
|
||||
auto newZ = -sinTheta * x + cosTheta * 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);
|
||||
}
|
||||
|
||||
bool hit(const ray& r, interval rayT, hitRecord& rec) const override {
|
||||
// Change the ray from world space to object space.
|
||||
auto origin = r.origin();
|
||||
auto direction = r.direction();
|
||||
|
||||
origin[0] = cosTheta * r.origin()[0] - sinTheta * r.origin()[2];
|
||||
origin[2] = sinTheta * r.origin()[0] + cosTheta * r.origin()[2];
|
||||
|
||||
|
||||
direction[0] = cosTheta * r.direction()[0] - sinTheta * r.direction()[2];
|
||||
direction[2] = sinTheta * r.direction()[0] + cosTheta * r.direction()[2];
|
||||
|
||||
ray rotatedR(origin, direction, r.time());
|
||||
|
||||
// Determine whether an intersection exists in object space (and if so, where).
|
||||
if (!object->hit(rotatedR, rayT, rec)) return false;
|
||||
|
||||
// Change the intersection point from object space to world space.
|
||||
auto p = rec.p;
|
||||
p[0] = cosTheta * rec.p[0] + sinTheta * rec.p[2];
|
||||
p[2] = -sinTheta * rec.p[0] + cosTheta * rec.normal[2];
|
||||
|
||||
// Change the normal from object space to world space.
|
||||
auto normal = rec.normal;
|
||||
normal[0] = cosTheta * rec.normal[0] + sinTheta * rec.normal[2];
|
||||
normal[2] = -sinTheta * rec.normal[0] + cosTheta * rec.normal[2];
|
||||
|
||||
rec.p = p;
|
||||
rec.normal = normal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<hittable> object;
|
||||
double sinTheta;
|
||||
double cosTheta;
|
||||
aabb bBox;
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user