From 60b29d658dbaa9656076d92915b5c72653fe1775 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 9 Mar 2009 23:17:31 +0000 Subject: [PATCH 2/3] modified shapes and Scene to return surface normal in the intersect object git-svn-id: svn://anubis/fart/branches/2009-03-09_intersect_returning_normals@200 7f9b0f55-74a9-4bce-be96-3c2cd072584d --- main/Scene.cc | 44 +++++++++++++--------------- main/Scene.h | 19 +----------- shapes/Box.cc | 36 ++++++++++------------- shapes/Box.h | 1 - shapes/Cyl.cc | 71 ++++++++++++++++++--------------------------- shapes/Cyl.h | 1 - shapes/Intersect.cc | 11 +------ shapes/Intersect.h | 1 - shapes/Plane.cc | 12 +++----- shapes/Plane.h | 2 +- shapes/Shape.cc | 4 +-- shapes/Shape.h | 11 ++++--- shapes/Sphere.cc | 15 ++++------ shapes/Sphere.h | 1 - shapes/Subtract.cc | 29 +++++++++--------- shapes/Subtract.h | 1 - shapes/Union.cc | 11 +------ shapes/Union.h | 1 - 18 files changed, 100 insertions(+), 171 deletions(-) diff --git a/main/Scene.cc b/main/Scene.cc index 36569bb..be6be7d 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -148,27 +148,27 @@ Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor) { Color color; - ShapeDistance hit = getRayClosestHit(ray); + Shape::Intersection hit = getRayClosestHit(ray); if ( ! hit.shape.isNull() ) { /* compute the Phong lighting for each hit */ refptr material = hit.shape->getMaterial(); - Vector surfacePoint = ray[hit.dist]; - Vector surfaceNormal = hit.shape->getNormalAt(surfacePoint); - + /* TODO: make sure this can be removed */ +#if 0 /* check for backfaces */ if (ray.getDirection() % surfaceNormal > 0.0) { /* if dot product is positive, this is a back-face */ surfaceNormal = -surfaceNormal; } +#endif color = computePhong(material, ray, - surfacePoint, - surfaceNormal); + hit.position, + hit.normal); if (depth > 0 && factor > SCENE_FACTOR_THRESHOLD) { @@ -177,8 +177,8 @@ Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor) { color *= (1.0 - reflectance); Vector reflected_direction = - (-ray.getDirection()).reflect(surfaceNormal); - Ray newRay(surfacePoint, reflected_direction); + (-ray.getDirection()).reflect(hit.normal); + Ray newRay(hit.position, reflected_direction); Vector jitter_surface_point = newRay[0.0001]; Ray jitterNewRay(jitter_surface_point, reflected_direction); Color c = traceRayRecurse(jitterNewRay, @@ -191,7 +191,8 @@ Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor) if (factor * transparency > SCENE_FACTOR_THRESHOLD) { color *= (1.0 - transparency); - Vector jitter_surface_point = ray[hit.dist + 0.0001]; + Vector jitter_surface_point = hit.position + + ray.getDirection() * 0.0001; Ray newRay(jitter_surface_point, ray.getDirection()); Color c = traceRayRecurse(newRay, depth - 1, @@ -204,9 +205,10 @@ Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor) return color; } -Scene::ShapeDistance Scene::getRayClosestHit(const Ray & ray) +Shape::Intersection Scene::getRayClosestHit(const Ray & ray) { - ShapeDistance hit; + Shape::Intersection hit; + double min_dist = 0.0; bool foundOne = false; /* loop through all shapes in the scene */ @@ -221,12 +223,12 @@ Scene::ShapeDistance Scene::getRayClosestHit(const Ray & ray) i++) { refptr shape = intersections[i].shape; - const Vector & isect_point = intersections[i].vector; - double intersect_dist = (isect_point - ray.getOrigin()).mag(); - if (foundOne == false || intersect_dist < hit.dist) + const Vector & isect_point = intersections[i].position; + double intersect_dist = ray.getOrigin().dist_to(isect_point); + if (foundOne == false || intersect_dist < min_dist) { - hit.shape = shape; - hit.dist = intersect_dist; + hit = intersections[i]; + min_dist = intersect_dist; foundOne = true; } } @@ -306,12 +308,12 @@ double Scene::calculateLightContribution(const Ray & toLight, for (;;) { - ShapeDistance hit = getRayClosestHit(currentRay); + Shape::Intersection hit = getRayClosestHit(currentRay); if ( hit.shape.isNull() ) break; - double offset = hit.dist + 0.0001; + double offset = currentRay.getOrigin().dist_to(hit.position) + 0.0001; if ( dist_so_far + offset > dist_to_light ) break; @@ -327,9 +329,3 @@ double Scene::calculateLightContribution(const Ray & toLight, return contrib; } - -bool operator<(const Scene::ShapeDistance & sd1, - const Scene::ShapeDistance & sd2) -{ - return sd1.dist < sd2.dist; -} diff --git a/main/Scene.h b/main/Scene.h index acbd7d1..9133a58 100644 --- a/main/Scene.h +++ b/main/Scene.h @@ -22,20 +22,6 @@ class Scene { public: - /* types */ - class ShapeDistance - { - public: - ShapeDistance() {} - ShapeDistance(refptr shape, double dist) - { - this->shape = shape; - this->dist = dist; - } - refptr shape; - double dist; - }; - Scene(const std::map & options, const char * filename); ~Scene(); @@ -51,7 +37,7 @@ class Scene void renderPixel(int x, int y, unsigned char * pixel); Color traceRay(const Ray & ray); Color traceRayRecurse(const Ray & ray, int depth, double factor); - ShapeDistance getRayClosestHit(const Ray & ray); + Shape::Intersection getRayClosestHit(const Ray & ray); Color computePhong(const refptr material, const Ray & viewRay, const Vector & surfacePoint, @@ -102,8 +88,5 @@ class Scene unsigned char * m_data; }; -bool operator<(const Scene::ShapeDistance & sd1, - const Scene::ShapeDistance & sd2); - #endif diff --git a/shapes/Box.cc b/shapes/Box.cc index 2131020..5e2fb8c 100644 --- a/shapes/Box.cc +++ b/shapes/Box.cc @@ -45,8 +45,22 @@ Shape::IntersectionList Box::intersect(refptr _this, const Ray & ray) && (dim == 1 || fabs(isect_point[1]) <= m_size[1]) && (dim == 2 || fabs(isect_point[2]) <= m_size[2]) ) { + Vector normal(0, 0, -1); + + if ( FP_EQUAL(isect_point[0], m_size[0]) ) + normal = Vector(1, 0, 0); + else if ( FP_EQUAL(isect_point[0], -m_size[0]) ) + normal = Vector(-1, 0, 0); + else if ( FP_EQUAL(isect_point[1], m_size[1]) ) + normal = Vector(0, 1, 0); + else if ( FP_EQUAL(isect_point[1], -m_size[1]) ) + normal = Vector(0, -1, 0); + else if ( FP_EQUAL(isect_point[2], m_size[2]) ) + normal = Vector(0, 0, 1); + res.add(Intersection(_this, - m_transform.transform_point(isect_point)) + m_transform.transform_point(isect_point), + m_transform.transform_normal(normal)) ); } } @@ -56,23 +70,3 @@ Shape::IntersectionList Box::intersect(refptr _this, const Ray & ray) return res; } - -Vector Box::getNormalAt(const Vector & pt) -{ - Vector local_pt = m_inverse.transform_point(pt); - - Vector normal(0, 0, -1); - - if ( FP_EQUAL(local_pt[0], m_size[0]) ) - normal = Vector(1, 0, 0); - else if ( FP_EQUAL(local_pt[0], -m_size[0]) ) - normal = Vector(-1, 0, 0); - else if ( FP_EQUAL(local_pt[1], m_size[1]) ) - normal = Vector(0, 1, 0); - else if ( FP_EQUAL(local_pt[1], -m_size[1]) ) - normal = Vector(0, -1, 0); - else if ( FP_EQUAL(local_pt[2], m_size[2]) ) - normal = Vector(0, 0, 1); - - return m_transform.transform_normal(normal); -} diff --git a/shapes/Box.h b/shapes/Box.h index 556c385..d86b03f 100644 --- a/shapes/Box.h +++ b/shapes/Box.h @@ -9,7 +9,6 @@ class Box : public Shape public: Box(refptr size); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: Vector m_size; diff --git a/shapes/Cyl.cc b/shapes/Cyl.cc index 4b45b49..df40f8c 100644 --- a/shapes/Cyl.cc +++ b/shapes/Cyl.cc @@ -39,7 +39,8 @@ Shape::IntersectionList Cyl::intersect(refptr _this, const Ray & ray) <= m_bottom_radius_2) { res.add(Intersection(_this, - m_transform.transform_point(isect_point))); + m_transform.transform_point(isect_point), + m_transform.transform_normal(Vector(0, 0, -1)))); } } } @@ -57,7 +58,8 @@ Shape::IntersectionList Cyl::intersect(refptr _this, const Ray & ray) <= m_top_radius_2) { res.add(Intersection(_this, - m_transform.transform_point(isect_point))); + m_transform.transform_point(isect_point), + m_transform.transform_normal(Vector(0, 0, 1)))); } } } @@ -101,51 +103,34 @@ Shape::IntersectionList Cyl::intersect(refptr _this, const Ray & ray) Vector isect_point = ray_inv[solutions.results[i]]; if (isect_point[2] > 0.0 && isect_point[2] < m_height) { + Vector normal; + + if ( FP_EQUAL(m_slope, 0.0) ) + { + normal = Vector(isect_point[0], isect_point[1], 0.0); + } + else + { + double x = isect_point[0]; + double y = isect_point[1]; + double dist = sqrt( isect_point[0] * isect_point[0] + + isect_point[1] * isect_point[1] ); + if (dist > 0.0) + { + double scale = 1.0 / dist; + x *= scale; + y *= scale; + } + normal = Vector(x, y, m_inv_slope); + } + normal.normalize(); + res.add(Intersection(_this, - m_transform.transform_point(isect_point))); + m_transform.transform_point(isect_point), + m_transform.transform_normal(normal))); } } } return res; } - -Vector Cyl::getNormalAt(const Vector & pt) -{ - Vector local_pt = m_inverse.transform_point(pt); - - Vector normal; - - if ( FP_EQUAL(local_pt[2], 0.0) && m_bottom_radius > 0.0 ) - { - normal = Vector(0, 0, -1); - } - else if ( FP_EQUAL(local_pt[2], m_height) && m_top_radius > 0.0 ) - { - normal = Vector(0, 0, 1); - } - else - { - if ( FP_EQUAL(m_slope, 0.0) ) - { - normal = Vector(local_pt[0], local_pt[1], 0.0); - } - else - { - double x = local_pt[0]; - double y = local_pt[1]; - double dist = sqrt( local_pt[0] * local_pt[0] - + local_pt[1] * local_pt[1] ); - if (dist > 0.0) - { - double scale = 1.0 / dist; - x *= scale; - y *= scale; - } - normal = Vector(x, y, m_inv_slope); - } - normal.normalize(); - } - - return m_transform.transform_normal(normal); -} diff --git a/shapes/Cyl.h b/shapes/Cyl.h index e1eddf0..37714b0 100644 --- a/shapes/Cyl.h +++ b/shapes/Cyl.h @@ -9,7 +9,6 @@ class Cyl : public Shape public: Cyl(double bottom_radius, double top_radius, double height); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: double m_bottom_radius; diff --git a/shapes/Intersect.cc b/shapes/Intersect.cc index f142771..c94a749 100644 --- a/shapes/Intersect.cc +++ b/shapes/Intersect.cc @@ -21,8 +21,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.shape->getNormalAt( - merged[i].intersection.vector); + Vector normal = merged[i].intersection.normal; double dot = - (ray.getDirection() % normal); bool front = dot > 0.0; bool left = merged[i].left; @@ -56,11 +55,3 @@ Shape::IntersectionList Intersect::intersect(refptr _this, const Ray & ra return res; } - -Vector Intersect::getNormalAt(const Vector & pt) -{ - /* this should not be called */ - cerr << __FILE__ << ": " << __LINE__ << - ": error: Intersect::getNormalAt() was called!" << endl; - return Vector(0, 0, 0); -} diff --git a/shapes/Intersect.h b/shapes/Intersect.h index 4a975a7..35a9f1c 100644 --- a/shapes/Intersect.h +++ b/shapes/Intersect.h @@ -9,7 +9,6 @@ class Intersect : public Shape public: Intersect(refptr shape1, refptr shape2); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: refptr m_shape1; diff --git a/shapes/Plane.cc b/shapes/Plane.cc index f6a56c6..74f9769 100644 --- a/shapes/Plane.cc +++ b/shapes/Plane.cc @@ -11,6 +11,8 @@ Plane::Plane(double a, double b, double c, double d) m_b = b; m_c = c; m_d = d; + m_normal = Vector(m_a, m_b, m_c); + m_normal.normalize(); } Shape::IntersectionList Plane::intersect(refptr _this, const Ray & ray) @@ -42,15 +44,9 @@ Shape::IntersectionList Plane::intersect(refptr _this, const Ray & ray) { Vector isect_point = ray_inv[solutions.results[0]]; res.add(Intersection(_this, - m_transform.transform_point(isect_point))); + m_transform.transform_point(isect_point), + m_transform.transform_normal(m_normal))); } } return res; } - -Vector Plane::getNormalAt(const Vector & pt) -{ - Vector normal(m_a, m_b, m_c); - normal.normalize(); - return m_transform.transform_normal(normal); -} diff --git a/shapes/Plane.h b/shapes/Plane.h index 46fecce..94c3a01 100644 --- a/shapes/Plane.h +++ b/shapes/Plane.h @@ -9,10 +9,10 @@ class Plane : public Shape public: Plane(double a, double b, double c, double d); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: double m_a, m_b, m_c, m_d; + Vector m_normal; }; #endif diff --git a/shapes/Shape.cc b/shapes/Shape.cc index 940e8fa..6da0670 100755 --- a/shapes/Shape.cc +++ b/shapes/Shape.cc @@ -35,8 +35,8 @@ class BoolIntersectionComparator bool operator()(const Shape::BoolIntersection & i1, const Shape::BoolIntersection & i2) const { - return (m_refPoint.dist_to(i1.intersection.vector) - < m_refPoint.dist_to(i2.intersection.vector)); + return ( m_refPoint.dist_to(i1.intersection.position) + < m_refPoint.dist_to(i2.intersection.position) ); } protected: Vector m_refPoint; diff --git a/shapes/Shape.h b/shapes/Shape.h index 1e57b6f..ca86a0d 100644 --- a/shapes/Shape.h +++ b/shapes/Shape.h @@ -18,13 +18,17 @@ class Shape { public: Intersection() {}; - Intersection(refptr shape, const Vector & vector) + Intersection(refptr shape, + const Vector & position, + const Vector & normal) { this->shape = shape; - this->vector = vector; + this->position = position; + this->normal = normal; } refptr shape; - Vector vector; + Vector position; + Vector normal; }; class BoolIntersection { @@ -97,7 +101,6 @@ class Shape virtual ~Shape(); virtual IntersectionList intersect(refptr _this, const Ray & ray) = 0; - virtual Vector getNormalAt(const Vector & pt) = 0; void setTransform(Transform & t) { diff --git a/shapes/Sphere.cc b/shapes/Sphere.cc index 3e53bd1..d98e89f 100644 --- a/shapes/Sphere.cc +++ b/shapes/Sphere.cc @@ -30,19 +30,14 @@ Shape::IntersectionList Sphere::intersect(refptr _this, const Ray & ray) if (quadSolutions.results[i] >= 0.0) { Vector isect_point = ray_inv[quadSolutions.results[i]]; + Vector normal = isect_point; + normal.normalize(); res.add( - Intersection(_this, m_transform.transform_point(isect_point)) + Intersection(_this, + m_transform.transform_point(isect_point), + m_transform.transform_normal(normal)) ); } } return res; } - -Vector Sphere::getNormalAt(const Vector & pt) -{ - Vector normal = m_inverse.transform_point(pt); - - normal.normalize(); - - return m_transform.transform_normal(normal); -} diff --git a/shapes/Sphere.h b/shapes/Sphere.h index 165272e..9b83404 100644 --- a/shapes/Sphere.h +++ b/shapes/Sphere.h @@ -9,7 +9,6 @@ class Sphere : public Shape public: Sphere(double radius); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: double m_radius; diff --git a/shapes/Subtract.cc b/shapes/Subtract.cc index e44ba44..2115f96 100644 --- a/shapes/Subtract.cc +++ b/shapes/Subtract.cc @@ -21,8 +21,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.shape->getNormalAt( - merged[i].intersection.vector); + Vector normal = merged[i].intersection.normal; double dot = - (ray.getDirection() % normal); bool front = dot > 0.0; bool left = merged[i].left; @@ -32,25 +31,27 @@ Shape::IntersectionList Subtract::intersect(refptr _this, const Ray & ray in2 = front; if (!in_bool && in1 && !in2) { - /* we found an intersection point with the boolean object */ + /* we found an intersection point + * to get into the boolean object */ in_bool = true; - res.add( merged[i].intersection ); + BoolIntersection bi = merged[i]; + Intersection i = bi.intersection; + if ( ! left ) /* if this point came from object B (A - B) */ + i.normal = - i.normal; + res.add(i); } else if (in_bool && !(in1 && !in2)) { - /* we found an intersection point with the boolean object */ - res.add( merged[i].intersection ); + /* we found an intersection point + * to get out of the boolean object */ + BoolIntersection bi = merged[i]; + Intersection i = bi.intersection; + if ( ! left ) /* if this point came from object B (A - B) */ + i.normal = - i.normal; + res.add(i); in_bool = false; } } return res; } - -Vector Subtract::getNormalAt(const Vector & pt) -{ - /* this should not be called */ - cerr << __FILE__ << ": " << __LINE__ << - ": error: Subtract::getNormalAt() was called!" << endl; - return Vector(0, 0, 0); -} diff --git a/shapes/Subtract.h b/shapes/Subtract.h index fb44642..5d27b49 100644 --- a/shapes/Subtract.h +++ b/shapes/Subtract.h @@ -9,7 +9,6 @@ class Subtract : public Shape public: Subtract(refptr shape1, refptr shape2); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: refptr m_shape1; diff --git a/shapes/Union.cc b/shapes/Union.cc index 902872f..30dea21 100644 --- a/shapes/Union.cc +++ b/shapes/Union.cc @@ -21,8 +21,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.shape->getNormalAt( - merged[i].intersection.vector); + Vector normal = merged[i].intersection.normal; double dot = - (ray.getDirection() % normal); bool front = dot > 0.0; bool left = merged[i].left; @@ -56,11 +55,3 @@ Shape::IntersectionList Union::intersect(refptr _this, const Ray & ray) return res; } - -Vector Union::getNormalAt(const Vector & pt) -{ - /* this should not be called */ - cerr << __FILE__ << ": " << __LINE__ << - ": error: Union::getNormalAt() was called!" << endl; - return Vector(0, 0, 0); -} diff --git a/shapes/Union.h b/shapes/Union.h index bf9a9fb..1bd6130 100644 --- a/shapes/Union.h +++ b/shapes/Union.h @@ -9,7 +9,6 @@ class Union : public Shape public: Union(refptr shape1, refptr shape2); IntersectionList intersect(refptr _this, const Ray & ray); - Vector getNormalAt(const Vector & pt); protected: refptr m_shape1; From 51c5baf59a191ff12ca4966970dbea6f2d8bbedc Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 9 Mar 2009 23:21:23 +0000 Subject: [PATCH 3/3] updated subtract-subtract.fart and .todo git-svn-id: svn://anubis/fart/branches/2009-03-09_intersect_returning_normals@201 7f9b0f55-74a9-4bce-be96-3c2cd072584d --- .todo | 1 - scenes/subtract-subtract.fart | 11 ++++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.todo b/.todo index 22e7682..fd5944a 100644 --- a/.todo +++ b/.todo @@ -1,6 +1,5 @@ FART To-Do List =============== -- Fix subtractions of subtractions (inverting normals problem) - Shape definitions / reusability - Add distribution infrastructure - Add maximum recursion depth option / parameter diff --git a/scenes/subtract-subtract.fart b/scenes/subtract-subtract.fart index 9431b42..11fe6bc 100644 --- a/scenes/subtract-subtract.fart +++ b/scenes/subtract-subtract.fart @@ -3,7 +3,7 @@ scene { options { - multisample 2 + multisample 3 } camera @@ -17,6 +17,15 @@ scene position <-1, -3, 4> } + plane + { + position <0, 0, 1>, 1 + material + { + color <0, 1, 1> + } + } + subtract { box