]> git.tdb.fi Git - libs/math.git/blob - examples/raytrace.cpp
Add a raytracer example program
[libs/math.git] / examples / raytrace.cpp
1 #include <msp/core/application.h>
2 #include <msp/core/getopt.h>
3 #include <msp/core/inttypes.h>
4 #include <msp/geometry/loader.h>
5 #include <msp/io/buffered.h>
6 #include <msp/io/print.h>
7
8 using namespace std;
9 using namespace Msp;
10
11 class RayTracer: public RegisteredApplication<RayTracer>
12 {
13 private:
14         Geometry::Shape<double, 3> *shape;
15         unsigned width;
16         unsigned height;
17         string filename;
18         UInt8 *pixels;
19
20 public:
21         RayTracer(int, char **);
22         virtual ~RayTracer();
23
24         virtual int main();
25 private:
26         void load_shape();
27 };
28
29
30 RayTracer::RayTracer(int argc, char **argv):
31         shape(0),
32         width(500),
33         height(500),
34         pixels(new UInt8[width*height])
35 {
36         GetOpt getopt;
37         getopt.add_option('w', "width", width, GetOpt::REQUIRED_ARG);
38         getopt.add_option('h', "height", height, GetOpt::REQUIRED_ARG);
39         getopt.add_argument("filename", filename, GetOpt::REQUIRED_ARG);
40         getopt(argc, argv);
41 }
42
43 RayTracer::~RayTracer()
44 {
45         delete shape;
46         delete[] pixels;
47 }
48
49 int RayTracer::main()
50 {
51         load_shape();
52
53         for(unsigned y=0; y<height; ++y)
54         {
55                 double yf = 1.0-y*2.0/height;
56                 for(unsigned x=0; x<width; ++x)
57                 {
58                         double xf = x*2.0/width-1.0;
59                         Geometry::Ray<double, 3> ray(LinAl::Vector<double, 3>(0, 0, 5), LinAl::Vector<double, 3>(xf, yf, -2));
60                         Geometry::SurfacePoint<double, 3> points[4];
61                         unsigned count = shape->get_intersections(ray, points, 4);
62                         UInt8 *pixel = pixels+y*width+x;
63                         if(count)
64                                 *pixel = 255*(0.2+max(dot(points[0].normal, LinAl::Vector<double, 3>(0, 0, 1)), 0.0)*0.8);
65                         else
66                                 *pixel = 0;
67                 }
68         }
69
70         IO::Buffered cout_buf(IO::cout);
71         IO::print(cout_buf, "P2\n");
72         IO::print(cout_buf, "%d %d\n", width, height);
73         IO::print(cout_buf, "255\n");
74
75         for(unsigned y=0; y<height; ++y)
76         {
77                 for(unsigned x=0; x<width; ++x)
78                         IO::print(cout_buf, "%d ", pixels[y*width+x]);
79                 IO::print(cout_buf, "\n");
80         }
81
82         return 0;
83 }
84
85 void RayTracer::load_shape()
86 {
87         IO::BufferedFile in(filename);
88         DataFile::Parser parser(in, filename);
89         Geometry::Loader<double, 3> loader;
90         loader.load(parser);
91         shape = loader.get_shape().clone();
92 }