Add function to calculate sphere normal vector on given point on the sphere.

This commit is contained in:
Godzil
2020-02-17 15:39:14 +00:00
parent 656ff52204
commit a8194169c5
5 changed files with 92 additions and 0 deletions

View File

@@ -27,6 +27,8 @@ public:
Object(); Object();
virtual Intersect intersect(Ray r); virtual Intersect intersect(Ray r);
virtual Tuple normalAt(Tuple point);
void setTransform(Matrix transform); void setTransform(Matrix transform);
Ray transform(Ray r) { return Ray(this->transformMatrix * r.origin, this->transformMatrix * r.direction); }; Ray transform(Ray r) { return Ray(this->transformMatrix * r.origin, this->transformMatrix * r.direction); };
Ray invTransform(Ray r) { return Ray(this->inverseTransform * r.origin, this->inverseTransform * r.direction); }; Ray invTransform(Ray r) { return Ray(this->inverseTransform * r.origin, this->inverseTransform * r.direction); };

View File

@@ -18,6 +18,7 @@ class Sphere : public Object
public: public:
/* All sphere are at (0, 0, 0) and radius 1 in the object space */ /* All sphere are at (0, 0, 0) and radius 1 in the object space */
virtual Intersect intersect(Ray r); virtual Intersect intersect(Ray r);
virtual Tuple normalAt(Tuple point);
}; };
#endif //DORAYME_SPHERE_H #endif //DORAYME_SPHERE_H

View File

@@ -24,6 +24,11 @@ Intersect Object::intersect(Ray r)
return Intersect(); return Intersect();
}; };
Tuple Object::normalAt(Tuple point)
{
return Vector(0, 0, 0);
}
void Object::setTransform(Matrix transform) void Object::setTransform(Matrix transform)
{ {
this->transformMatrix = transform; this->transformMatrix = transform;

View File

@@ -35,4 +35,16 @@ Intersect Sphere::intersect(Ray r)
} }
return ret; return ret;
}
Tuple Sphere::normalAt(Tuple point)
{
Tuple object_point = this->inverseTransform * point;
Tuple object_normal = (object_point - Point(0, 0, 0)).normalise();
Tuple world_normal = this->inverseTransform.transpose() * object_normal;
/* W may get wrong, so hack it. This is perfectly normal as we are using a 4x4 matrix instead of a 3x3 */
world_normal.w = 0;
return world_normal.normalise();
} }

View File

@@ -105,4 +105,76 @@ TEST(SphereTest, Intersecting_a_translated_sphere_with_a_ray)
Intersect xs = s.intersect(r); Intersect xs = s.intersect(r);
ASSERT_EQ(xs.count(), 0); ASSERT_EQ(xs.count(), 0);
}
TEST(SphereTest, The_normal_on_a_sphere_at_a_point_on_the_X_axis)
{
Sphere s = Sphere();
Tuple n = s.normalAt(Point(1, 0, 0));
ASSERT_EQ(n, Vector(1, 0, 0));
}
TEST(SphereTest, The_normal_on_a_sphere_at_a_point_on_the_Y_axis)
{
Sphere s = Sphere();
Tuple n = s.normalAt(Point(0, 1, 0));
ASSERT_EQ(n, Vector(0, 1, 0));
}
TEST(SphereTest, The_normal_on_a_sphere_at_a_point_on_the_Z_axis)
{
Sphere s = Sphere();
Tuple n = s.normalAt(Point(0, 0, 1));
ASSERT_EQ(n, Vector(0, 0, 1));
}
TEST(SphereTest, The_normal_on_a_sphere_at_a_nonaxial_point)
{
Sphere s = Sphere();
Tuple n = s.normalAt(Point(sqrt(3)/3, sqrt(3)/3, sqrt(3)/3));
ASSERT_EQ(n, Vector(sqrt(3)/3, sqrt(3)/3, sqrt(3)/3));
}
TEST(SphereTest, The_normal_is_a_normalise_vector)
{
Sphere s = Sphere();
Tuple n = s.normalAt(Point(sqrt(3)/3, sqrt(3)/3, sqrt(3)/3));
ASSERT_EQ(n, n.normalise());
}
TEST(SphereTest, Computing_the_normal_on_a_translated_sphere)
{
Sphere s = Sphere();
s.setTransform(translation(0, 1, 0));
Tuple n = s.normalAt(Point(0, 1.70711, -0.70711));
set_equal_precision(0.0001);
ASSERT_EQ(n, Vector(0, 0.70711, -0.70711));
/* Revert to default */
set_equal_precision(FLT_EPSILON);
}
TEST(SphereTest, Computing_the_normal_on_a_tranformed_sphere)
{
Sphere s = Sphere();
s.setTransform(scaling(1, 0.5, 1) * rotation_z(M_PI / 5));
Tuple n = s.normalAt(Point(0, sqrt(2)/2, -sqrt(2)/2));
set_equal_precision(0.0001);
ASSERT_EQ(n, Vector(0, 0.97014, -0.24254));
/* Revert to default */
set_equal_precision(FLT_EPSILON);
} }