Advertisement
Guest User

ззз

a guest
Mar 20th, 2018
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.34 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2.  
  3. #include <cstdio>
  4.  
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <vector>
  8. #include <string>
  9.  
  10. using namespace std;
  11.  
  12. #define INF 999999999.9
  13.  
  14. const double Vw = 1;
  15. const double Vh = 1;
  16. const double D = 1;
  17. const double Cw = 720;
  18. const double Ch = 720;
  19. const int recursion_depth = 5;
  20.  
  21. int clamp(double v, double mn, double mx)
  22. {
  23.     return (max(mn, min(v, mx))) / 1;
  24. }
  25.  
  26. struct vec
  27. {
  28.     vec()
  29.     {
  30.         x = y = z = 0;
  31.     }
  32.  
  33.     vec(double x_, double y_, double z_)
  34.     {
  35.         x = x_;
  36.         y = y_;
  37.         z = z_;
  38.     }
  39.  
  40.     double dot(const vec &other) const
  41.     {
  42.         return x * other.x + y * other.y + z * other.z;
  43.     }
  44.  
  45.     double length() const
  46.     {
  47.         return sqrt(x * x + y * y + z * z);
  48.     }
  49.  
  50.     vec add(double k) const
  51.     {
  52.         return vec(k + x, k + y, k + z);
  53.     }
  54.  
  55.     vec add(const vec &other) const
  56.     {
  57.         return vec(x + other.x, y + other.y, z + other.z);
  58.     }
  59.  
  60.     vec sub(const vec &other) const
  61.     {
  62.         return vec(x - other.x, y - other.y, z - other.z);
  63.     }
  64.  
  65.     vec operator-() const
  66.     {
  67.         return vec(-x, -y, -z);
  68.     }
  69.  
  70.     vec mult(double k) const
  71.     {
  72.         return vec(k * x, k * y, k * z);
  73.     }
  74.  
  75.     vec mult(const vec &other) const
  76.     {
  77.         return vec(x * other.x, y * other.y, z * other.z);
  78.     }
  79.     vec normalized() {
  80.         return vec(x / length(), y / length(), z / length());
  81.     }
  82.  
  83.     double x, y, z;
  84. };
  85. vec ReflectRay(vec R, vec N) {
  86.     return N.mult(N.dot(R) * 2).sub(R);
  87. }
  88.  
  89.  
  90. std::ostream &operator <<(std::ostream &os, const vec &v)
  91. {
  92.     return os << "vec(" << v.x << ", " << v.y << ", " << v.z << ")";
  93. }
  94.  
  95. struct color_t
  96. {
  97.     color_t()
  98.     {
  99.         r = g = b = 255;
  100.     }
  101.  
  102.     color_t(double r_, double g_, double b_)
  103.     {
  104.         r = r_;
  105.         g = g_;
  106.         b = b_;
  107.     }
  108.  
  109.     color_t add(double k) const
  110.     {
  111.         return color_t(k + r, k + g, k + b);
  112.     }
  113.  
  114.     color_t add(const color_t &other) const
  115.     {
  116.         return color_t(r + other.r, g + other.g, b + other.b);
  117.     }
  118.  
  119.     color_t mult(double k) const
  120.     {
  121.         return color_t(k * r, k * g, k * b);
  122.     }
  123.  
  124.     color_t normalized() const
  125.     {
  126.         return color_t(clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255));
  127.     }
  128.  
  129.     double r, g, b;
  130. };
  131.  
  132. struct sphere_t
  133. {
  134.     sphere_t()
  135.     {
  136.         radius = 0;
  137.         color = color_t();
  138.         center = vec();
  139.         specular = -1.0;
  140.         reflective = 0;
  141.     }
  142.  
  143.     sphere_t(const vec &center_, double radius_, const color_t &color_, double specular_, double reflective_)
  144.     {
  145.         radius = radius_;
  146.         center = center_;
  147.         color = color_;
  148.         specular = specular_;
  149.         reflective = reflective_;
  150.     }
  151.  
  152.     pair<double, double> getIntersectionsWith(const vec &O, const vec &D)
  153.     {
  154.         vec OC = O.sub(center);
  155.  
  156.         double k1 = D.dot(D);
  157.         double k2 = 2 * OC.dot(D);
  158.         double k3 = OC.dot(OC) - radius * radius;
  159.  
  160.         double d = k2 * k2 - 4 * k1 * k3;
  161.         if (d < 0)
  162.             return pair<double, double>(INF + 2.0, INF + 2.0);
  163.  
  164.         double t1 = (-k2 + sqrt(d)) / (2.0 * k1);
  165.         double t2 = (-k2 - sqrt(d)) / (2.0 * k1);
  166.  
  167.         return pair<double, double>(t1, t2);
  168.     }
  169.  
  170.     color_t color;
  171.     vec center;
  172.     double radius;
  173.     double specular;
  174.     double reflective;
  175. };
  176. struct light_t
  177. {
  178.     enum type_t { AMBIENT, POINT, DIRECTIONAL };
  179.     light_t(double i, type_t type_, vec A = vec())
  180.     {
  181.         intensity = i;
  182.         type = type_;
  183.         v = A;
  184.     }
  185.     type_t type;
  186.     vec v;
  187.     double intensity;
  188. };
  189. vector<light_t>lights;
  190. pair<int, double> ClosestIntersection(vec O, vec D, double t_min, double t_max);
  191. double ComputeLightning(const vec &P, const vec &N, const vec &V, double s)
  192. {
  193.     double i = 0.0;
  194.     for (int j = 0; j < lights.size(); ++j)
  195.     {
  196.         if (lights[j].type == light_t::type_t::AMBIENT) {
  197.             i += lights[j].intensity;
  198.         }
  199.         else
  200.         {
  201.             vec L;
  202.             if (lights[j].type == light_t::type_t::POINT) {
  203.                 L = lights[j].v.sub(P);
  204.             }
  205.             else
  206.             {
  207.                 L = lights[j].v;
  208.             }
  209.             pair<int, double> p = ClosestIntersection(P, L, 0.001, INF);
  210.             if (p.first >= 0)
  211.                 continue;
  212.  
  213.             double NDL = N.dot(L);
  214.             if (NDL > 0)
  215.             {
  216.                 i += lights[j].intensity * NDL / (N.length() * L.length());
  217.             }
  218.  
  219.             if (s > 0)
  220.             {
  221.                 vec R = ReflectRay(N, L);
  222.                 double RDV = R.dot(V);
  223.                 if (RDV > 0)
  224.                 {
  225.                     i += lights[j].intensity * pow(RDV / (R.length() * V.length()), s);
  226.                 }
  227.             }
  228.         }
  229.     }
  230.  
  231.     return i;
  232. }
  233.  
  234.  
  235. vector<sphere_t> spheres;
  236.  
  237. typedef vector<vector<color_t>> data_t;
  238.  
  239. data_t normalized(const data_t &v)
  240. {
  241.     data_t r(v.size(), vector<color_t>(v[0].size()));
  242.     for (size_t i = 0; i < v.size(); ++i)
  243.     {
  244.         for (size_t j = 0; j < v[i].size(); ++j)
  245.         {
  246.             r[i][j] = v[i][j].normalized();
  247.         }
  248.     }
  249.  
  250.     return r;
  251. }
  252.  
  253. void writeImage(const string &filename, const data_t &data_)
  254. {
  255.     data_t data = normalized(data_);
  256.     int h = data.size();
  257.     int w = data[0].size();
  258.  
  259.     FILE *f;
  260.     int filesize = 54 + 3 * w*h;  //w is your image width, h is image height, both int
  261.  
  262.     vector<unsigned char> img(3 * w * h, 0);
  263.  
  264.     for (int i = 0; i<w; i++)
  265.     {
  266.         for (int j = 0; j<h; j++)
  267.         {
  268.             int x = i, y = (h - 1) - j;
  269.             int r = data[i][j].r;
  270.             int g = data[i][j].g;
  271.             int b = data[i][j].b;
  272.             img[(x + y * w) * 3 + 2] = (unsigned char)(r);
  273.             img[(x + y * w) * 3 + 1] = (unsigned char)(g);
  274.             img[(x + y * w) * 3 + 0] = (unsigned char)(b);
  275.         }
  276.     }
  277.  
  278.     unsigned char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 };
  279.     unsigned char bmpinfoheader[40] = { 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0 };
  280.     unsigned char bmppad[3] = { 0,0,0 };
  281.  
  282.     bmpfileheader[2] = (unsigned char)(filesize);
  283.     bmpfileheader[3] = (unsigned char)(filesize >> 8);
  284.     bmpfileheader[4] = (unsigned char)(filesize >> 16);
  285.     bmpfileheader[5] = (unsigned char)(filesize >> 24);
  286.  
  287.     bmpinfoheader[4] = (unsigned char)(w);
  288.     bmpinfoheader[5] = (unsigned char)(w >> 8);
  289.     bmpinfoheader[6] = (unsigned char)(w >> 16);
  290.     bmpinfoheader[7] = (unsigned char)(w >> 24);
  291.     bmpinfoheader[8] = (unsigned char)(h);
  292.     bmpinfoheader[9] = (unsigned char)(h >> 8);
  293.     bmpinfoheader[10] = (unsigned char)(h >> 16);
  294.     bmpinfoheader[11] = (unsigned char)(h >> 24);
  295.  
  296.     f = fopen(filename.c_str(), "wb");
  297.     fwrite(bmpfileheader, 1, 14, f);
  298.     fwrite(bmpinfoheader, 1, 40, f);
  299.  
  300.     const unsigned char *pimg = img.data();
  301.     for (int i = 0; i<h; i++)
  302.     {
  303.         fwrite(pimg + (w*(h - i - 1) * 3), 3, w, f);
  304.         fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
  305.     }
  306.  
  307.     fclose(f);
  308. }
  309.  
  310. vec canvasToViewport(double x, double y)
  311. {
  312.     return vec(x * Vw / Cw, y * Vh / Ch, D);
  313. }//
  314. pair<int, double> ClosestIntersection(vec O, vec D, double t_min, double t_max)
  315. {
  316.     double min_d = -1;
  317.     int closest_id = -1;
  318.     for (int i = 0; i < spheres.size(); ++i)
  319.     {
  320.         pair<double, double> p;
  321.         p = spheres[i].getIntersectionsWith(O, D);
  322.         if ((min_d < 0 || min_d >= p.first) && t_min <= p.first && p.first <= t_max)
  323.         {
  324.             min_d = p.first;
  325.             closest_id = i;
  326.         }
  327.  
  328.         if ((min_d < 0 || min_d >= p.second) && t_min <= p.second && p.second <= t_max)
  329.         {
  330.             min_d = p.second;
  331.             closest_id = i;
  332.         }
  333.     }
  334.     return make_pair(closest_id, min_d);
  335. }
  336. //
  337. color_t traceRay(const vec &O, const vec &D, double t_min, double t_max, int recursion_depth)
  338. {
  339.     int closest_id = -1;
  340.     double min_d = -1;
  341.     pair<int, double> p = make_pair(-1, -1);
  342.     p = ClosestIntersection(O, D, t_min, t_max);
  343.     if (p.first < 0)
  344.     {
  345.         return color_t(0, 0, 0); // BACKGROUND_COLOR
  346.     }
  347.     vec P = O.add(D.mult(p.second));
  348.     vec N = P.sub(spheres[p.first].center).normalized();
  349.     color_t local_color = spheres[p.first].color.mult(ComputeLightning(P, N, -D, spheres[p.first].specular));
  350.     double r = spheres[p.first].reflective;
  351.     color_t reflected_color = color_t();
  352.  
  353.     if (r<=0||recursion_depth<=0)
  354.         return local_color;
  355.     else{
  356.         vec R = ReflectRay(-D, N);
  357.         reflected_color = traceRay(P, R, 0.001, INF, recursion_depth-1);
  358.         return local_color.mult(1-r).add(reflected_color.mult(r));
  359.     }
  360. }
  361. int main()
  362. {
  363.     vec O (0, 0, 0);
  364.     spheres.push_back(sphere_t(vec(0, -1, 3), 1, color_t(255, 0, 0), 500, 0.2));
  365.     spheres.push_back(sphere_t(vec(2, 0, 4), 1, color_t(0, 0, 255), 500, 0.3));
  366.     spheres.push_back(sphere_t(vec(-2, 0, 3), 1, color_t(0, 255, 0), 10, 0.4));
  367.     spheres.push_back(sphere_t(vec(0, -5001, 0), 5000, color_t(255, 255, 0), 1000, 1));
  368.     lights.push_back(light_t(0.2, light_t::AMBIENT));
  369.     lights.push_back(light_t(0.6, light_t::POINT, vec(2, 1, 0)));
  370.     lights.push_back(light_t(0.2, light_t::DIRECTIONAL, vec(1, 4, 4)));
  371.     data_t image(Ch, vector<color_t>(Cw));
  372.  
  373.     for (int y = -Ch / 2; y < Ch / 2; ++y)
  374.     {
  375.         for (int x = -Cw / 2; x < Cw / 2; ++x)
  376.         {
  377.             vec D = canvasToViewport(y, x);
  378.             color_t color = traceRay(O, D, 1, INF, 3);
  379.             image[y + Ch / 2][x + Cw / 2] = color;
  380.         }
  381.     }
  382.  
  383.     writeImage("result.bmp", image);
  384.  
  385.     return 0;
  386. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement