]> git.tdb.fi Git - libs/math.git/blob - examples/raytrace.cpp
Use the proper array size in the raytrace example
[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         vector<Geometry::SurfacePoint<double, 3> > points(shape->get_max_ray_intersections());
54
55         for(unsigned y=0; y<height; ++y)
56         {
57                 double yf = 1.0-y*2.0/height;
58                 for(unsigned x=0; x<width; ++x)
59                 {
60                         double xf = x*2.0/width-1.0;
61                         Geometry::Ray<double, 3> ray(LinAl::Vector<double, 3>(0, 0, 5), LinAl::Vector<double, 3>(xf, yf, -2));
62                         unsigned count = shape->get_intersections(ray, &points[0], points.size());
63                         UInt8 *pixel = pixels+y*width+x;
64                         if(count)
65                                 *pixel = 255*(0.2+max(dot(points[0].normal, LinAl::Vector<double, 3>(0, 0, 1)), 0.0)*0.8);
66                         else
67                                 *pixel = 0;
68                 }
69         }
70
71         IO::Buffered cout_buf(IO::cout);
72         IO::print(cout_buf, "P2\n");
73         IO::print(cout_buf, "%d %d\n", width, height);
74         IO::print(cout_buf, "255\n");
75
76         for(unsigned y=0; y<height; ++y)
77         {
78                 for(unsigned x=0; x<width; ++x)
79                         IO::print(cout_buf, "%d ", pixels[y*width+x]);
80                 IO::print(cout_buf, "\n");
81         }
82
83         return 0;
84 }
85
86 void RayTracer::load_shape()
87 {
88         IO::BufferedFile in(filename);
89         DataFile::Parser parser(in, filename);
90         Geometry::Loader<double, 3> loader;
91         loader.load(parser);
92         shape = loader.get_shape().clone();
93 }