diff --git a/main/Scene-load.cc b/main/Scene-load.cc index ee34cd9..8fa78ca 100644 --- a/main/Scene-load.cc +++ b/main/Scene-load.cc @@ -532,6 +532,7 @@ refptr Scene::processBool(refptr node) refptr material; bool restore_transform = processTransforms(node); + m_transforms.push(Transform()); for (Node_Iterator it = node->getChildren().begin(); it != node->getChildren().end(); @@ -559,11 +560,6 @@ refptr Scene::processBool(refptr node) { processShapeDefinition(*it); } - else - { - cerr << "Error: unknown boolean object item" << endl; - exit(3); - } } if (shapes.size() < 2) @@ -589,8 +585,9 @@ refptr Scene::processBool(refptr node) if ( ! material.isNull() ) shape->setMaterial(material); - shape->setTransform(m_transforms.top()); + m_transforms.pop(); + shape->setTransform(m_transforms.top()); if (restore_transform) m_transforms.pop(); @@ -715,7 +712,7 @@ refptr Scene::processShapeRef(refptr node) != m_shape_definitions.end()) { refptr shape = m_shape_definitions[node->getString()]->clone(); - shape->setTransform(m_transforms.top()); + shape->setTransform(m_transforms.top() * shape->getTransform()); return shape; } cerr << "Error: no shape definition for '" << node->getString() @@ -766,6 +763,8 @@ bool Scene::processTransforms(refptr node) void Scene::processShapeDefinition(refptr node) { + m_transforms.push(Transform()); m_shape_definitions[node->getString()] = processShape(node->getChildren()[0]); + m_transforms.pop(); } diff --git a/shapes/Intersect.cc b/shapes/Intersect.cc index b8adbf7..a4c421e 100644 --- a/shapes/Intersect.cc +++ b/shapes/Intersect.cc @@ -31,9 +31,10 @@ Intersect::Intersect(const vector< refptr > & shapes) Shape::IntersectionList Intersect::intersect(refptr _this, const Ray & ray) { - IntersectionList res1 = m_shape1->intersect(m_shape1, ray); - IntersectionList res2 = m_shape2->intersect(m_shape2, ray); - BoolIntersectionList merged(res1, res2, ray.getOrigin()); + Ray ray_inv = m_inverse.transform_ray(ray); + IntersectionList res1 = m_shape1->intersect(m_shape1, ray_inv); + IntersectionList res2 = m_shape2->intersect(m_shape2, ray_inv); + BoolIntersectionList merged(res1, res2, ray_inv.getOrigin()); IntersectionList res; bool in1 = false, in2 = false; @@ -45,7 +46,7 @@ Shape::IntersectionList Intersect::intersect(refptr _this, const Ray & ra i++) { Vector normal = merged[i].intersection.normal; - double dot = - (ray.getDirection() % normal); + double dot = - (ray_inv.getDirection() % normal); bool back = dot < 0.0; bool left = merged[i].left; if (back) @@ -65,7 +66,7 @@ Shape::IntersectionList Intersect::intersect(refptr _this, const Ray & ra for (int i = 0, sz = merged.size(); i < sz; i++) { Vector normal = merged[i].intersection.normal; - double dot = - (ray.getDirection() % normal); + double dot = - (ray_inv.getDirection() % normal); bool front = dot > 0.0; bool left = merged[i].left; if (front) @@ -78,7 +79,7 @@ Shape::IntersectionList Intersect::intersect(refptr _this, const Ray & ra { /* we found an intersection point with the boolean object */ in_bool = true; - res.add( merged[i].intersection ); + res.add( merged[i].intersection.transform(m_transform) ); } } else @@ -86,7 +87,7 @@ Shape::IntersectionList Intersect::intersect(refptr _this, const Ray & ra if (in_bool && in1 && in2) { /* we found an intersection point with the boolean object */ - res.add( merged[i].intersection ); + res.add( merged[i].intersection.transform(m_transform) ); } if (left) in1 = false; diff --git a/shapes/Shape.h b/shapes/Shape.h index b5ad9c6..5e78d41 100644 --- a/shapes/Shape.h +++ b/shapes/Shape.h @@ -29,6 +29,12 @@ class Shape refptr shape; Vector position; Vector normal; + Intersection transform(Transform & t) + { + return Intersection(shape, + t.transform_point(position), + t.transform_normal(normal)); + } }; class BoolIntersection { @@ -103,10 +109,10 @@ class Shape const Ray & ray) = 0; virtual refptr clone() = 0; - void setTransform(Transform & t) + void setTransform(const Transform & t) { m_transform = t; - m_inverse = t.getInverse(); + m_inverse = m_transform.getInverse(); } Transform & getTransform() { return m_transform; } diff --git a/shapes/Subtract.cc b/shapes/Subtract.cc index a61f6de..a2f2d94 100644 --- a/shapes/Subtract.cc +++ b/shapes/Subtract.cc @@ -31,9 +31,10 @@ Subtract::Subtract(const vector< refptr > & shapes) Shape::IntersectionList Subtract::intersect(refptr _this, const Ray & ray) { - IntersectionList res1 = m_shape1->intersect(m_shape1, ray); - IntersectionList res2 = m_shape2->intersect(m_shape2, ray); - BoolIntersectionList merged(res1, res2, ray.getOrigin()); + Ray ray_inv = m_inverse.transform_ray(ray); + IntersectionList res1 = m_shape1->intersect(m_shape1, ray_inv); + IntersectionList res2 = m_shape2->intersect(m_shape2, ray_inv); + BoolIntersectionList merged(res1, res2, ray_inv.getOrigin()); IntersectionList res; bool in1 = false, in2 = false; @@ -45,7 +46,7 @@ Shape::IntersectionList Subtract::intersect(refptr _this, const Ray & ray i++) { Vector normal = merged[i].intersection.normal; - double dot = - (ray.getDirection() % normal); + double dot = - (ray_inv.getDirection() % normal); bool back = dot < 0.0; bool left = merged[i].left; if (back) @@ -65,7 +66,7 @@ Shape::IntersectionList Subtract::intersect(refptr _this, const Ray & ray for (int i = 0, sz = merged.size(); i < sz; i++) { Vector normal = merged[i].intersection.normal; - double dot = - (ray.getDirection() % normal); + double dot = - (ray_inv.getDirection() % normal); bool front = dot > 0.0; bool left = merged[i].left; if (left) @@ -81,7 +82,7 @@ Shape::IntersectionList Subtract::intersect(refptr _this, const Ray & ray Intersection i = bi.intersection; if ( ! left ) /* if this point came from object B (A - B) */ i.normal = - i.normal; - res.add(i); + res.add(i.transform(m_transform)); } else if (in_bool && !(in1 && !in2)) { @@ -91,7 +92,7 @@ Shape::IntersectionList Subtract::intersect(refptr _this, const Ray & ray Intersection i = bi.intersection; if ( ! left ) /* if this point came from object B (A - B) */ i.normal = - i.normal; - res.add(i); + res.add(i.transform(m_transform)); in_bool = false; } } diff --git a/shapes/Union.cc b/shapes/Union.cc index 5000b33..e8d81d8 100644 --- a/shapes/Union.cc +++ b/shapes/Union.cc @@ -32,9 +32,10 @@ Union::Union(const vector< refptr > & shapes) Shape::IntersectionList Union::intersect(refptr _this, const Ray & ray) { - IntersectionList res1 = m_shape1->intersect(m_shape1, ray); - IntersectionList res2 = m_shape2->intersect(m_shape2, ray); - BoolIntersectionList merged(res1, res2, ray.getOrigin()); + Ray ray_inv = m_inverse.transform_ray(ray); + IntersectionList res1 = m_shape1->intersect(m_shape1, ray_inv); + IntersectionList res2 = m_shape2->intersect(m_shape2, ray_inv); + BoolIntersectionList merged(res1, res2, ray_inv.getOrigin()); IntersectionList res; bool in1 = false, in2 = false; @@ -46,7 +47,7 @@ Shape::IntersectionList Union::intersect(refptr _this, const Ray & ray) i++) { Vector normal = merged[i].intersection.normal; - double dot = - (ray.getDirection() % normal); + double dot = - (ray_inv.getDirection() % normal); bool back = dot < 0.0; bool left = merged[i].left; if (back) @@ -66,7 +67,7 @@ Shape::IntersectionList Union::intersect(refptr _this, const Ray & ray) for (int i = 0, sz = merged.size(); i < sz; i++) { Vector normal = merged[i].intersection.normal; - double dot = - (ray.getDirection() % normal); + double dot = - (ray_inv.getDirection() % normal); bool front = dot > 0.0; bool left = merged[i].left; if (front) @@ -79,7 +80,7 @@ Shape::IntersectionList Union::intersect(refptr _this, const Ray & ray) { /* we found an intersection point with the boolean object */ in_bool = true; - res.add( merged[i].intersection ); + res.add( merged[i].intersection.transform(m_transform) ); } } else @@ -91,7 +92,7 @@ Shape::IntersectionList Union::intersect(refptr _this, const Ray & ray) if (in_bool && !(in1 || in2)) { /* we found an intersection point with the boolean object */ - res.add( merged[i].intersection ); + res.add( merged[i].intersection.transform(m_transform) ); in_bool = false; } } diff --git a/util/Transform.cc b/util/Transform.cc index c7853bc..ea76787 100644 --- a/util/Transform.cc +++ b/util/Transform.cc @@ -104,3 +104,10 @@ Ray Transform::transform_ray(const Ray & r) Ray res(newPosition, newDirection); return res; } + +Transform Transform::operator*(const Transform & other) const +{ + Transform t; + t.m_matrix = m_matrix * other.m_matrix; + return t; +} diff --git a/util/Transform.h b/util/Transform.h index eeaef69..da9654f 100644 --- a/util/Transform.h +++ b/util/Transform.h @@ -36,6 +36,7 @@ class Transform Vector transform_direction(const Vector & v); Vector transform_normal(const Vector & v); Ray transform_ray(const Ray & r); + Transform operator*(const Transform & other) const; protected: Matrix m_matrix;