Implement instance rotation
This commit is contained in:
74
hittable.h
74
hittable.h
@@ -64,4 +64,78 @@ class translate : public hittable {
|
|||||||
aabb bBox;
|
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
|
#endif
|
Reference in New Issue
Block a user