diff --git a/src/SConscript b/src/SConscript index e9fae8e..517ae22 100644 --- a/src/SConscript +++ b/src/SConscript @@ -28,6 +28,7 @@ files = [ 'objectPlane.cc', 'reader_yaml.cc', 'scene.cc', + 'stats.cc', 'writer_png.cc', ] diff --git a/src/object.h b/src/object.h index 67706ca..c621fc1 100644 --- a/src/object.h +++ b/src/object.h @@ -15,6 +15,7 @@ #include "basics.h" #include "material.h" +#include "stats.hh" #include "texture.h" #include "types.hh" @@ -42,7 +43,7 @@ struct Object * @param [out] t A vector of all intersection t values * @return `true` if the ray intersects with this object */ - virtual bool DoesIntersect(const Ray& ray, TVector& t) const = 0; + virtual bool DoesIntersect(const Ray& ray, TVector& t, Stats& stats) const = 0; virtual bool point_is_on_surface(const Vector3 &p) const = 0; virtual Vector3 compute_normal(const Vector3 &p) const = 0; diff --git a/src/objectBox.cc b/src/objectBox.cc index b2af53d..e467e4e 100644 --- a/src/objectBox.cc +++ b/src/objectBox.cc @@ -53,9 +53,12 @@ Box::SetFar(const Vector3& far) bool Box::DoesIntersect(const Ray& ray, - TVector& t) + TVector& t, + Stats& stats) const { + stats.boxIntersectionTests++; + /* * XXX: For now, I'm assuming that all boxes are parallel to the coordinate * axes. This is the Kay-Kajiya box intersection algorithm. @@ -174,8 +177,10 @@ Box::DoesIntersect(const Ray& ray, } /* We have an intersection! */ + stats.boxIntersections++; t.push_back(tNear); t.push_back(tFar); + return true; } diff --git a/src/objectBox.hh b/src/objectBox.hh index b0dd746..714b2fe 100644 --- a/src/objectBox.hh +++ b/src/objectBox.hh @@ -21,7 +21,7 @@ struct Box Vector3& GetFar(); void SetFar(const Vector3& far); - bool DoesIntersect(const Ray& ray, TVector& t) const; + bool DoesIntersect(const Ray& ray, TVector& t, Stats& stats) const; bool point_is_on_surface(const Vector3 &p) const; Vector3 compute_normal(const Vector3 &p) const; diff --git a/src/objectPlane.cc b/src/objectPlane.cc index 8c022e7..d80d813 100644 --- a/src/objectPlane.cc +++ b/src/objectPlane.cc @@ -60,7 +60,8 @@ Plane::SetDistance(Double distance) */ bool Plane::DoesIntersect(const Ray &ray, - TVector& t) + TVector& t, + Stats& stats) const { /* @@ -70,7 +71,7 @@ Plane::DoesIntersect(const Ray &ray, * * A * x + B * y + C * z + D = 0, where * A^2 + B^2 + C^2 = 1. - * + * * The sign of D determines which side of the origin the plane is on. * * We can figure out the distance from the ray's origin to the intersection @@ -80,7 +81,7 @@ Plane::DoesIntersect(const Ray &ray, * indicated with lowercase letters (ROx is the x component of RO). * * A(ROx + RDx * t) + B(ROy + RDy * t) + C(ROz + RDz * t) + D = 0 - * + * * We then solve for t. * * t = -(A * ROx + B * ROy + C * ROz + D) / (A * RDx + B * RDy + C * RDz) @@ -90,6 +91,8 @@ Plane::DoesIntersect(const Ray &ray, * t = -(n . RO + D) / (n . RD) */ + stats.planeIntersectionTests++; + /* The denominator for the t equation above. */ Double vd = mNormal.dot(ray.direction); if (NearZero(vd)) { @@ -110,6 +113,7 @@ Plane::DoesIntersect(const Ray &ray, return false; } + stats.planeIntersections++; t.push_back(t0); return true; } diff --git a/src/objectPlane.hh b/src/objectPlane.hh index 612798f..f3463f8 100644 --- a/src/objectPlane.hh +++ b/src/objectPlane.hh @@ -30,7 +30,7 @@ public: /** * @see charles::Object::DoesIntersect */ - bool DoesIntersect(const Ray &ray, TVector& t) const; + bool DoesIntersect(const Ray &ray, TVector& t, Stats& stats) const; bool point_is_on_surface(const Vector3 &p) const; Vector3 compute_normal(const Vector3 &p) const; diff --git a/src/object_sphere.cc b/src/object_sphere.cc index 6505921..4e83a4a 100644 --- a/src/object_sphere.cc +++ b/src/object_sphere.cc @@ -66,9 +66,12 @@ Sphere::set_radius(float r) */ bool Sphere::DoesIntersect(const Ray& ray, - TVector& t) + TVector& t, + Stats& stats) const { + stats.sphereIntersectionTests++; + /* Origin of the vector in object space. */ Vector3 rayOriginObj = ray.origin - GetOrigin(); @@ -119,6 +122,7 @@ Sphere::DoesIntersect(const Ray& ray, } } + stats.sphereIntersections++; return true; } diff --git a/src/object_sphere.h b/src/object_sphere.h index d703504..8a69552 100644 --- a/src/object_sphere.h +++ b/src/object_sphere.h @@ -26,7 +26,7 @@ public: float get_radius(); void set_radius(float r); - bool DoesIntersect(const Ray& ray, TVector& t) const; + bool DoesIntersect(const Ray& ray, TVector& t, Stats& stats) const; bool point_is_on_surface(const Vector3 &p) const; Vector3 compute_normal(const Vector3 &p) const; private: diff --git a/src/scene.cc b/src/scene.cc index 5f90c54..2b1046b 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -174,6 +174,8 @@ Scene::render() printf("Rendering completed in %f seconds.\n\n", seconds.count()); LOG_INFO << "Rendering completed in " << seconds.count() << " seconds."; mStats.PrintRayTable(); + printf("\n"); + mStats.PrintIntersectionsTable(); } @@ -225,7 +227,7 @@ Scene::trace_ray(const Ray &ray, // Find intersections of this ray with objects in the scene. for (Object::Ptr s : shapes) { ts.clear(); - if (s->DoesIntersect(ray, ts)) { + if (s->DoesIntersect(ray, ts, mStats)) { for (Double t : ts) { if (t < 1e-2) { break; @@ -279,7 +281,7 @@ Scene::trace_ray(const Ray &ray, /* Figure out if we're in shadow. */ ts.clear(); - if (s->DoesIntersect(shadowRay, ts)) { + if (s->DoesIntersect(shadowRay, ts, mStats)) { diffuse_level = 0.0; break; } @@ -323,38 +325,3 @@ Scene::trace_ray(const Ray &ray, return out_color; } - - -unsigned long -Scene::Stats::TotalRays() - const -{ - return primaryRays + shadowRays + reflectionRays + transmissionRays; -} - - -void -Scene::Stats::PrintRayTable() - const -{ - printf("RAY TYPE NUM %%\n"); - printf("-------------- ---------- ------\n"); - PrintRayRow("primary", primaryRays); - PrintRayRow("shadow", shadowRays); - PrintRayRow("reflection", reflectionRays); - PrintRayRow("transmission", transmissionRays); - PrintRayRow("total", TotalRays()); -} - - -void -Scene::Stats::PrintRayRow(const std::string& title, - const unsigned long& value) - const -{ - double totalRays = TotalRays(); - printf("%-14s %10ld %#5.1lf%%\n", - title.c_str(), - value, - double(value) / totalRays * 100.0); -} diff --git a/src/scene.h b/src/scene.h index bbdeffe..93ae813 100644 --- a/src/scene.h +++ b/src/scene.h @@ -16,6 +16,7 @@ #include "basics.h" #include "camera.h" #include "object.h" +#include "stats.hh" class AmbientLight; @@ -70,22 +71,7 @@ private: std::list lights; // Rendering stats - struct Stats - { - unsigned long TotalRays() const; - - void PrintRayTable() const; - - /* Ray counts */ - unsigned long primaryRays; - unsigned long shadowRays; - unsigned long reflectionRays; - unsigned long transmissionRays; - - private: - void PrintRayRow(const std::string& title, - const unsigned long& value) const; - } mStats; + charles::Stats mStats; // Rendering output. bool _is_rendered; diff --git a/src/stats.cc b/src/stats.cc new file mode 100644 index 0000000..345e5c1 --- /dev/null +++ b/src/stats.cc @@ -0,0 +1,92 @@ +/* stats.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include +#include + +#include "stats.hh" + + +namespace charles{ + +Stats::Stats() + : primaryRays(), + shadowRays(), + reflectionRays(), + transmissionRays(), + boxIntersections(), + boxIntersectionTests(), + planeIntersections(), + planeIntersectionTests(), + sphereIntersections(), + sphereIntersectionTests() +{ } + + +unsigned long +Stats::TotalRays() + const +{ + return primaryRays + shadowRays + reflectionRays + transmissionRays; +} + + +void +Stats::PrintRayTable() + const +{ + printf("RAY TYPE NUM %%\n"); + printf("-------------- ---------- ------\n"); + PrintRayRow("primary", primaryRays); + PrintRayRow("shadow", shadowRays); + PrintRayRow("reflection", reflectionRays); + PrintRayRow("transmission", transmissionRays); + PrintRayRow("total", TotalRays()); +} + + +void +Stats::PrintIntersectionsTable() + const +{ + printf("SHAPE INTS TESTS SUCC %%\n"); + printf("-------------- ---------- ---------- -------\n"); + if (boxIntersectionTests > 0) { + PrintIntersectionsRow("boxes", boxIntersections, boxIntersectionTests); + } + if (planeIntersectionTests > 0) { + PrintIntersectionsRow("planes", planeIntersections, planeIntersectionTests); + } + if (sphereIntersectionTests > 0) { + PrintIntersectionsRow("spheres", sphereIntersections, sphereIntersectionTests); + } +} + + +void +Stats::PrintRayRow(const std::string& title, + const unsigned long& value) + const +{ + double totalRays = TotalRays(); + printf("%-14s %10ld %#6.1lf%%\n", + title.c_str(), + value, + double(value) / totalRays * 100.0); +} + + +void +Stats::PrintIntersectionsRow(const std::string& title, + const unsigned long& num, + const unsigned long& total) + const +{ + printf("%-14s %10ld %10ld %#5.1lf%%\n", + title.c_str(), + num, total, double(num) / double(total) * 100.0); +} + +} /* namespace charles */ diff --git a/src/stats.hh b/src/stats.hh new file mode 100644 index 0000000..0f535ca --- /dev/null +++ b/src/stats.hh @@ -0,0 +1,44 @@ +/* stats.hh + * vim: set tw=80: + * Eryn Wells + */ + +#ifndef __STATS_HH__ +#define __STATS_HH__ + +namespace charles { + +struct Stats +{ + Stats(); + + unsigned long TotalRays() const; + + void PrintRayTable() const; + void PrintIntersectionsTable() const; + + /* Ray counts */ + unsigned long primaryRays; + unsigned long shadowRays; + unsigned long reflectionRays; + unsigned long transmissionRays; + + /* Intersection counts */ + unsigned long boxIntersections; + unsigned long boxIntersectionTests; + unsigned long planeIntersections; + unsigned long planeIntersectionTests; + unsigned long sphereIntersections; + unsigned long sphereIntersectionTests; + +private: + void PrintRayRow(const std::string& title, + const unsigned long& value) const; + void PrintIntersectionsRow(const std::string& title, + const unsigned long& num, + const unsigned long& total) const; +}; + +} /* namespace charles */ + +#endif /* __STATS_HH__ */