<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【Ray Tracing The Next Week 超詳解】 光線追蹤2-9

       

      我們來(lái)整理一下項(xiàng)目的代碼

      目錄

      ----include

      --hit

      --texture

      --material

      ----RTdef.hpp

      ----ray.hpp

      ----camera.hpp

      ----main.cpp

       

      3D泛型數(shù)學(xué)庫(kù)中的randomfunc.hpp增加了新內(nèi)容

       

      #pragma once
      
      #include <lvgm\type_vec\type_vec.h>
      #include <random>
      
      namespace lvgm
      {
      
      //@brief:    create a random number that from 0 to 1 completely
      template<typename T = lvgm::precision>
          const T rand01()
              {
              if (typeid(T) == typeid(int))
                  {
                  std::cerr << "integer doesn't have a random number from 0 to 1\n";
                  throw "integer doesn't have a random number from 0 to 1\n";
                  }
          
              static std::mt19937 mt;
              static std::uniform_real_distribution<T> r;
              return r(mt);
              }
      
      
      //@brief:    find a random point in unit_sphere
      template<typename T = lvgm::precision>
          const lvgm::vec3<T> random_unit_sphere()    
              {
              if (typeid(T) == typeid(int))
                  {
                  std::cerr << "integer doesn't have a random number from 0 to 1\n";
                  throw "integer doesn't have a random number from 0 to 1\n";
                  }
      
              lvgm::vec3<T> p;
              do
                  {
                  p = 2.0*lvgm::vec3<T>(rand01(), rand01(), rand01()) - lvgm::vec3<T>(1, 1, 1);
                  } while (dot(p, p) >= 1.0);
              return p;
              }
      
      
      //@brief:    find a random point in unit_plane
      template<typename T = lvgm::precision>
          const lvgm::vec2<T> random_unit_plane()            
              {
              if (typeid(T) == typeid(int))
                  {
                  std::cerr << "integer doesn't have a random number from 0 to 1\n";
                  throw "integer doesn't have a random number from 0 to 1\n";
                  }
      
              lvgm::vec2<T> p;
              do
                  {
                  p = 2.0*lvgm::vec2<T>(rand01(), rand01()) - lvgm::vec2<T>(1, 1);
                  } while (dot(p, p) >= 1.0);
              return p;
              }
      
      //@brief:    generate a list of normalized vector(-1~1)
      template<typename T = precision>
          vec2<T> * random_normalized2D(const size_t size)
              {
              vec2<T> * p = new vec2<T>[size];
              for (int i = 0; i < size; ++i)
                  p[i] = vec2<T>( -1 + 2 * lvgm::rand01(), -1 + 2 * lvgm::rand01()).ret_unitization();
              return p;
              }
      
      //@brief:    generate a list of normalized vector(-1~1)
      template<typename T = precision>
          vec3<T> * random_normalized3D(const size_t size)
              {
              vec3<T> * p = new vec3<T>[size];
              for (int i = 0; i < size; ++i)
                  p[i] = vec3<T>(-1 + 2 * lvgm::rand01(), -1 + 2 * lvgm::rand01(), -1 + 2 * lvgm::rand01()).ret_unitization();
              return p;
              }
      
      //@brief:    generate a list of normalized vector(-1~1)
      template<typename T = precision>
          T * random_normalized1D(const size_t size)
              {
              T * p = new T[size];
              for (int i = 0; i < size; ++i)
                  p[i] = -1 + 2 * lvgm::rand01();
              return p;
              }
      
      //@brief:    make list permute randomly
      template<typename T>
          void permute_method(T * p, size_t n)
              {
              for (int i = n - 1; i; i--)
                  {
                  size_t tar = int(lvgm::rand01() * (i + 1));
                  T t = p[i];
                  p[i] = p[tar];
                  p[tar] = t;
                  }
              }
      
      //@brief:    generate a list of random value(0~n)
      template<typename T = int>
          T * generate_random0n(size_t size)
              {
              int * p = new int[size];
              for (int i = 0; i < 256; ++i)    p[i] = i;
              permute_method(p, 256);
              return p;
              }
      
      }
      randomfunc.hpp

       

       

       

      先說(shuō)最外面的

      基本和上次的沒什么區(qū)別http://www.rzrgm.cn/lv-anchoret/p/10243553.html

      /// RTdef.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10243553.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1.1
      // [brief ]        the basic concept of rt
      // -----------------------------------------------------
      
      #pragma once
      
      #include <lvgm\type_vec\type_vec.h>        //http://www.rzrgm.cn/lv-anchoret/p/10163085.html
      #include <lvgm\opticsfunc.hpp>            //http://www.rzrgm.cn/lv-anchoret/p/10241904.html
      #include <lvgm\randfunc.hpp>            //http://www.rzrgm.cn/lv-anchoret/p/10241904.html
      #include <algorithm>
      
      #define stds std::
      
      namespace rt
      {
          using rtvar = lvgm::precision;
      
          using rtvec = lvgm::vec3<rtvar>;
      
          constexpr static rtvar rtInf() { return static_cast<rtvar>(0x3f3f3f3f); }        //最大值
      
          constexpr rtvar π = 3.1415926;
      
          template<typename T>
          const T& rtmin(const T& a, const T& b)
          {
              return a < b ? a : b;
          }
      
          template<typename T>
          const T& rtmax(const T& a, const T& b)
          {
              return a > b ? a : b;
          }
      
      }
      RTdef.hpp

       

      /// ray.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10182002.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        the ray-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      
      #pragma once
      
      #include "RTdef.hpp"
      
      namespace rt
      {
      
      class ray
          {
      public:
          ray()
              :_a{ rtvec() }
              , _b{ rtvec() }
          {  }
      
          ray(const rtvec& a, const rtvec& b, const rtvar time = 0.)
              :_a(a)
              , _b(b)
              ,_time(time)
          {  }
      
          ray(const ray& r)
              :_a(r._a)
              ,_b(r._b)
              ,_time(r._time)
          {    }
      
          inline rtvec origin()const        { return _a; }
      
          inline rtvec direction()const    { return _b; }
      
          inline rtvar time()const        { return _time; }
      
          inline rtvec go(const rtvar t)const { return _a + t * _b; }
      
      private:
          rtvec _a;
      
          rtvec _b;
      
          rtvar _time;
      
          };
      } // rt namespace 
      ray.hpp

       

      /// camera.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10221058.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        the camera-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of camera class
      
      class camera
          {
      public:
      
          /*
          @brief: the camera constructor
          @param: lookfrom -> the position of eye
                  lookat -> the vector of sight's direction
                  vup -> the vertical up direction
                  vfov -> 相機(jī)在垂直方向上關(guān)于屏幕岔開的角度
                  aspect -> Screen aspect ratio
                  focus -> the focal length
                  t1 -> Shutter start time
                  t2 -> Shutter end time
          */
          camera(rtvec lookfrom, rtvec lookat, rtvec vup, rtvar vfov, rtvar aspect, rtvar aperture, rtvar focus, rtvar t1, rtvar t2);
      
          inline const ray get_ray(const rtvar u, const rtvar v)const;
      
          inline const ray get_ray(const lvgm::vec2<rtvar>& para)const;
      
      public:
          inline const rtvec& eye()const { return _eye; }
      
          inline const rtvec& start()const { return _start; }
      
          inline const rtvec& horizontal()const { return _horizontal; }
      
          inline const rtvec& vertical()const { return _vertical; }
      
          inline const rtvec& u()const { return _u; }
      
          inline const rtvec& v()const { return _v; }
      
          inline const rtvec& w()const { return _w; }
      
          inline const rtvar lens_r()const { return _lens_radius; }
      
      private:
          rtvec _u;
      
          rtvec _v;
      
          rtvec _w;
      
          rtvec _eye;
      
          rtvec _start;        //left-bottom
      
          rtvec _horizontal;
      
          rtvec _vertical;
      
          rtvar _lens_radius;  //the radius of lens
      
          rtvar _time1;
      
          rtvar _time2;
      
          };
      
      
      
      //the implementation of camera class
      
      inline camera::camera(rtvec lookfrom, rtvec lookat, rtvec vup, rtvar vfov, rtvar aspect, rtvar aperture, rtvar focus, rtvar t1, rtvar t2)
          :_eye(lookfrom)
          , _lens_radius(aperture / 2)
          , _time1(t1)
          , _time2(t2)
          {
          rtvar theta = vfov * π / 180;
          rtvar half_height = tan(theta / 2) * focus;
          rtvar half_width = aspect * half_height;
          _w = (lookfrom - lookat).ret_unitization();
          _u = cross(vup, _w).ret_unitization();
          _v = cross(_w, _u);
          
          _start = _eye - half_width * _u - half_height * _v - focus * _w;//高和寬都乘了焦距,w也要乘,不然公式是錯(cuò)的
          _horizontal = 2 * half_width * _u;
          _vertical = 2 * half_height * _v;
          }
      
      inline const ray camera::get_ray(const rtvar u, const rtvar v)const
          {
          rtvec rd = rtvec(_lens_radius * lvgm::random_unit_plane());
          rtvec offset = _u * rd.x() + _v * rd.y();
          rtvar time = _time1 + lvgm::rand01() * (_time2 - _time1);
          return ray{ _eye + offset, _start + u*_horizontal + v*_vertical - (_eye + offset), time };
          }
      
      inline     const ray camera::get_ray(const lvgm::vec2<rtvar>& para)const
          {
          return get_ray(para.u(), para.v()); 
          }
      
      } // rt namespace 
      camera.hpp

       

       hit

      里面包含的很多物體以及一些變換

      /// RThit.hpp
      //    http://www.rzrgm.cn/lv-anchoret/p/10190092.html
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        some intersects
      //                intersections
      //                aabb
      //                bvh
      //                sphere
      //                moving_sphere
      //                rectangle
      //                rectangles
      //                box
      //                translate
      //                rotate
      // -----------------------------------------------------
      
      #pragma once
      
      #include "ray.hpp"
      #include "aabb_box.hpp"
      #include "intersect.hpp"
      
      #include "bvh.hpp"
      #include "intersections.hpp"
      
      #include "sphere.hpp"
      #include "moving_sphere.hpp"
      #include "rectangleBasic.hpp"
      #include "rectangles.hpp"
      #include "rectangle.hpp"
      #include "flip_normal.hpp"
      #include "box.hpp"
      #include "constant_medium.hpp"
      
      #include "translate.hpp"
      #include "rotate.hpp"
      RThit.hpp

       

      /// intersect.hpp
      //http://www.rzrgm.cn/lv-anchoret/p/10190092.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        the intersect-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      class material;
      class aabb;
      
      
      // the infomation of intersection point
      
      struct hitInfo
          {
          lvgm::precision _t;        //ray 中的系數(shù)t
          rtvec _p;                //相交點(diǎn)、撞擊點(diǎn)
          rtvec _n;                //_p點(diǎn)的表面法線
          material* _materialp;    //材質(zhì)
          rtvar _u;                //texture-u
          rtvar _v;                //texture-v
          };
      
      
      // the statement of intersect class
      
      class intersect
          {
      public:
          intersect() {  }
      
          /*
          @brief: 撞擊函數(shù),求取撞擊點(diǎn)相關(guān)記錄信息
          @param: sight->視線
          系數(shù)t的上下界->篩選撞擊點(diǎn)
          info->返回撞擊點(diǎn)信息
          @retur: 是否存在合法撞擊點(diǎn)
          */
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const = 0;
      
          /*
          @brief: get the box of Geometry
          */
          virtual aabb getbox()const = 0;
      
          };
      
      }
      intersect.hpp

       

      /// aabb.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10284085.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the aabb-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      //the statement of aabb class
      
      class aabb
          {
      public:
          aabb() {  }
      
          /*
          @brief: the box of Geometry
          @param: min -> 盒子坐標(biāo)最小端
                  max -> 盒子坐標(biāo)最大端
          */
          aabb(const rtvec& min, const rtvec& max);
      
          /*
          @brief: 相交碰撞檢測(cè)
          @param: sight -> 視線
                  解的上下界
          @retur: 是否碰撞相交
          */
          inline bool hit(const ray& sight, rtvar tmin, rtvar tmax)const;
      
          /*
          @brief: 兩個(gè)包圍盒的包圍盒
          */
          static aabb _surrounding_box(aabb box1, aabb box2);
          
      public:
      
          inline const rtvec& min()const { return _min; }
      
          inline const rtvec& max()const { return _max; }
      
      private:
          rtvec _min;
      
          rtvec _max;
          };
      
      
      //the implementation of aabb class
      
      inline aabb::aabb(const rtvec& min, const rtvec& max)
          :_min(min)
          ,_max(max)
          {
          }
      
      inline bool aabb::hit(const ray& sight, rtvar tmin, rtvar tmax)const
          {
          for (int i = 0; i < 3; ++i)
              {
              rtvar div = 1.0 / sight.direction()[i];
              rtvar t1 = (_min[i] - sight.origin()[i]) / sight.direction()[i];
              rtvar t2 = (_max[i] - sight.origin()[i]) / sight.direction()[i];
              if (div < 0.)stds swap(t1, t2);
              if (stds min(t2, tmax) <= stds max(t1, tmin))
                  return false;
              }
          return true;
          }
      
      aabb aabb::_surrounding_box(aabb box1, aabb box2)
          {
          auto fmin = [](const rtvar a, const rtvar b) {return a < b ? a : b; };
          auto fmax = [](const rtvar a, const rtvar b) {return a > b ? a : b; };
          rtvec min{    fmin(box1.min().x(),box2.min().x()),
                      fmin(box1.min().y(),box2.min().y()),
                      fmin(box1.min().z(),box2.min().z()) };
          rtvec max{    fmax(box1.max().x(),box2.max().x()),
                      fmax(box1.max().y(),box2.max().y()),
                      fmax(box1.max().z(),box2.max().z()) };
          return aabb(min, max);
          }
      
      }  //rt namespace 
      aabb.hpp

       

      /// bvh.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10284085.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the bvh-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of bvh_node class
      
      class bvh_node :public intersect
          {
      public:
          bvh_node() {  }
      
          /*
          @brief: bvh樹
          @param: world -> all Geometry of the scene
                  n -> the number of the Geometry
                  time1 -> start time
                  time2 -> end time
          */
          bvh_node(intersect** world, const int n, const rtvar time1, const rtvar time2);
      
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
      private:
          intersect* _left;
      
          intersect* _right;
      
          aabb _box;
      
          };
      
      
      // the implementation of bvh_node class
      
      inline    int _x_cmp(const void * lhs, const void * rhs)
          {
          intersect * lc = *(intersect**)lhs;
          intersect * rc = *(intersect**)rhs;
          aabb lbox = lc->getbox();
          aabb rbox = rc->getbox();
      
          if (lbox.min().x() - rbox.min().x() < 0.)
              return -1;
          else
              return 1;
          }
      
      inline    int _y_cmp(const void * lhs, const void * rhs)
          {
          intersect * lc = *(intersect**)lhs;
          intersect * rc = *(intersect**)rhs;
          aabb lbox = lc->getbox();
          aabb rbox = rc->getbox();
      
          if (lbox.min().y() - rbox.min().y() < 0.)
              return -1;
          else
              return 1;
          }
      
      inline    int _z_cmp(const void * lhs, const void * rhs)
          {
          intersect * lc = *(intersect**)lhs;
          intersect * rc = *(intersect**)rhs;
          aabb lbox = lc->getbox();
          aabb rbox = rc->getbox();
          if (lbox.min().z() - rbox.min().z() < 0.)
              return -1;
          else
              return 1;
          }
      
      inline bvh_node::bvh_node(intersect** world, const int n, const rtvar time1, const rtvar time2)
          {
          int axis = static_cast<int>(3 * lvgm::rand01());
          if (axis == 0)
              qsort(world, n, sizeof(intersect*), _x_cmp);
          else if (axis == 1)
              qsort(world, n, sizeof(intersect*), _y_cmp);
          else
              qsort(world, n, sizeof(intersect*), _z_cmp);
      
          if (n == 1)
              _left = _right = world[0];
          else if (n == 2)
              _left = world[0],
              _right = world[1];
          else
              _left = new bvh_node(world, n / 2, time1, time2),
              _right = new bvh_node(world + n / 2, n - n / 2, time1, time2);
      
          aabb lbox = _left->getbox();
          aabb rbox = _right->getbox();
      
          _box = aabb::_surrounding_box(lbox, rbox);
          }
      
      aabb bvh_node::getbox()const
          {
          return _box;
          }
      
      bool bvh_node::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          if (_box.hit(sight, t_min, t_max))
              {
              hitInfo linfo, rinfo;
              bool lhit = _left->hit(sight, t_min, t_max, linfo);
              bool rhit = _right->hit(sight, t_min, t_max, rinfo);
              if (lhit && rhit)
                  {
                  if (linfo._t < rinfo._t)
                      info = linfo;
                  else
                      info = rinfo;
                  return true;
                  }
              else if (lhit)
                  {
                  info = linfo;
                  return true;
                  }
              else if (rhit)
                  {
                  info = rinfo;
                  return true;
                  }
              else 
                  return false;
              }
          else 
              return false;
          }
      
      } //rt namespace
      bvh.hpp

       

      /// intersections.hpp
      //    http://www.rzrgm.cn/lv-anchoret/p/10190092.html
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        the intersections-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of intersections class
      
      class intersections :public intersect
          {
      public:
          intersections() {  }
      
      
          /*
          @brief: the list of scene's Geometry
          @param: list -> all Geometry of the scene
                  n -> the number of the scene's Geometry
          */    
          intersections(intersect** list, size_t n) :_list(list), _size(n) {  }
              
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override { return aabb(); }
      
      public:
          const size_t get_size()const { return _size; }
      
      private:
          intersect** _list;
      
          size_t _size;
          };
      
      
      
      // the implementation of intersections class
      
      bool intersections::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          hitInfo t_rec;
          bool hitSomething = false;
          rtvar far = t_max;            //剛開始可以看到無(wú)限遠(yuǎn)
          for (int i = 0; i < _size; ++i)
              {
              if (_list[i]->hit(sight, t_min, far, t_rec))
                  {
                  hitSomething = true;
                  far = t_rec._t;            //將上一次的最近撞擊點(diǎn)作為視線可達(dá)最遠(yuǎn)處
                  info = t_rec;
                  }
              }
          return hitSomething;
          }
      
      
      } // rt namespace 
      intersections.hpp

       

      /// sphere.hpp
      //  http://www.rzrgm.cn/lv-anchoret/p/10190092.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the sphere-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      #pragma once
      
      namespace rt
      {
      
      class sphere :public intersect
          {
      public:
          sphere() {  }
      
              /*
              @para1: 球心坐標(biāo)
              @para2: 球半徑
              @para3: 材質(zhì)
              */
          sphere(const rtvec& h, rtvar r, material* ma);
      
          ~sphere();
              
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
          /*
          獲取幾何球體中p點(diǎn)對(duì)應(yīng)的2D紋理坐標(biāo)(u,v)
          */
          static void get_sphere_uv(const rtvec& p, rtvar& u, rtvar& v);
      
      public:
      
          inline const rtvar r()const            { return _radius;    }
      
          inline const rtvec& heart()const    { return _heart;    }
      
          inline const material* get_material()const { return _materialp; }
      
          inline rtvar& r()                    { return _radius;    }
      
          inline rtvec& heart()                { return _heart;    }
      
          inline void set_material(material* m) { _materialp = m; }
      private:
          rtvec _heart;
      
          rtvar _radius;
      
          material* _materialp;
          };
      
      
      inline sphere::sphere(const rtvec& h, rtvar r, material* ma) 
          :_heart(h)
          , _radius(r)
          , _materialp(ma)
          {
          }
      
      inline sphere::~sphere() 
          {
          if (_materialp)
              delete _materialp; 
          }
      
      bool sphere::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvec trace = sight.origin() - _heart;
          rtvar a = dot(sight.direction(), sight.direction());
          rtvar b = 2.0 * dot(trace, sight.direction());
          rtvar c = dot(trace, trace) - _radius * _radius;
          rtvar delt = b*b - 4.0*a*c;
          if (delt > 0)
              {
              info._materialp = _materialp;
              rtvar x = (-b - sqrt(delt)) / (2.0*a);
              if (x < t_max && x > t_min)
                  {
                  info._t = x;
                  info._p = sight.go(x);
                  info._n = (info._p - _heart) / _radius;
                  get_sphere_uv((info._p - _heart) / _radius, info._u, info._v);        //將撞擊點(diǎn)向量規(guī)格化
                  return true;
                  }
              x = (-b + sqrt(delt)) / (2.0*a);
              if (x < t_max && x > t_min)
                  {
                  info._t = x;
                  info._p = sight.go(x);
                  info._n = (info._p - _heart) / _radius;
                  get_sphere_uv((info._p - _heart) / _radius, info._u, info._v);        //!!!
                  return true;
                  }
              }
          return false;
          }
      
      aabb sphere::getbox()const
          {
          return aabb(_heart - rtvec(_radius, _radius, _radius), _heart + rtvec(_radius, _radius, _radius));
          }
      
      void sphere::get_sphere_uv(const rtvec& p, rtvar& u, rtvar& v)
          {
          rtvar φ = atan2(p.z(), p.x());
          rtvar θ = asin(p.y());
          u = 1 - (φ + π) / (2 * π);
          v = (θ + π / 2) / π;
          }
      
      } // rt namespace
      sphere.hpp

       

      /// moving_sphere.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10269488.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the moving_sphere-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      //the statement of moving_shpere class
      
      class moving_sphere :public intersect 
          {
      public:
          moving_sphere() {  }
      
          /*
          @brief: 模擬運(yùn)動(dòng)模糊的幾何體
          @param: 起始位置的球心
                  結(jié)束位置的球心
                  開始時(shí)間
                  結(jié)束時(shí)間
                  球體半徑
                  紋理
          */
          moving_sphere(rtvec heart1, rtvec heart2, rtvar t1, rtvar t2, rtvar r, material* mp);
      
          virtual bool hit(const ray& r, rtvar tmin, rtvar tmax, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
          inline rtvec heart(rtvar t)const;
          
      private:
          rtvec _heart1;
          rtvec _heart2;
          rtvar _time1;
          rtvar _time2;
          rtvar _radius;
          material* _materialp;
          };
      
      
      
      //the implementation of moving_sphere class
      
      inline moving_sphere::moving_sphere(rtvec heart1, rtvec heart2, rtvar t1, rtvar t2, rtvar r, material* mp)
          :_heart1(heart1)
          , _heart2(heart2)
          , _time1(t1)
          , _time2(t2)
          , _radius(r)
          , _materialp(mp)
          {
          }
      
      inline rtvec moving_sphere::heart(rtvar t)const
          {
          return _heart1 + ((t - _time1) / (_time2 - _time1)) * (_heart2 - _heart1);
          }
      
      bool moving_sphere::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvec trace = sight.origin() - heart(sight.time());
          rtvar a = dot(sight.direction(), sight.direction());
          rtvar b = 2.0 * dot(trace, sight.direction());
          rtvar c = dot(trace, trace) - _radius * _radius;
          rtvar delt = b*b - 4.0*a*c;
          if (delt > 0)
              {
              info._materialp = _materialp;
              rtvar x = (-b - sqrt(delt)) / (2.0*a);
              if (x < t_max && x > t_min)
                  {
                  info._t = x;
                  info._p = sight.go(x);
                  info._n = (info._p - heart(sight.time())) / _radius;
                  return true;
                  }
              x = (-b + sqrt(delt)) / (2.0*a);
              if (x < t_max && x > t_min)
                  {
                  info._t = x;
                  info._p = sight.go(x);
                  info._n = (info._p - heart(sight.time())) / _radius;
                  return true;
                  }
              }    
          return false;
          }
      
      aabb moving_sphere::getbox()const
          {
          rtvec delt{ _radius, _radius, _radius };
          return aabb::_surrounding_box(aabb(_heart1 - delt, _heart1 + delt), aabb(_heart2 - delt, _heart2 + delt));
          }
      
      } // rt namespace
      moving_sphere.hpp

       

      /// constant_medium.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the constant_dedium-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      
      #pragma once
      
      namespace rt
      {
      
      class constant_medium :public intersect
          {
      public:
          /*
          形體
          顆粒濃度
          紋理
          */
          constant_medium(intersect* p, rtvar d, texture* tex);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
      public:
          inline const rtvar get_density()const { return _density; }
      
          inline const material* get_material()const { return _materialp; }
      
          inline void set_density(const rtvar density) { _density = density; }
      
          inline void set_material(material* m) { _materialp = m; }
      
      private:
          intersect* _item;
      
          rtvar _density;
      
          material* _materialp;
          };
      
      
      
      inline constant_medium::constant_medium(intersect* p, rtvar d, texture* tex)
          :_item(p)
          ,_density(d)
          ,_materialp(new isotropic(tex))
          {
          }
      
      aabb constant_medium::getbox()const
          {
          return _item->getbox();
          }
      
      bool constant_medium::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const 
          {
          hitInfo info1, info2;
          if (_item->hit(sight, -rtInf(), rtInf(), info1)) {
              if (_item->hit(sight, info1._t + 0.0001, rtInf(), info2)) {
                  if (info1._t < t_min)
                      info1._t = t_min;
                  if (info2._t > t_max)
                      info2._t = t_max;
                  if (info1._t >= info2._t)
                      return false;
                  if (info1._t < 0)
                      info1._t = 0;
                  float distance_inside_boundary = (info2._t - info1._t)*sight.direction().normal();
                  float hit_distance = -(1 / _density)*log(lvgm::rand01());
                  if (hit_distance < distance_inside_boundary) {
                      info._t = info1._t + hit_distance / sight.direction().normal();
                      info._p = sight.go(info._t);
                      info._n = rtvec(lvgm::rand01(), lvgm::rand01(), lvgm::rand01());  // arbitrary
                      info._materialp = _materialp;
                      return true;
                      }
                  }
              }
          return false;
          }
      
      } // rt namespace
      constant_medium.hpp

       

      /// flip_normal.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10307569.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the flip_normal-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
          
      class flip_normal: public intersect
          {
      public:
          flip_normal(intersect * p) :_p(p) {  }
          
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override
              {
              if (_p->hit(sight, t_min, t_max, info))
                  {
                  info._n = -info._n;
                  return true;
                  }
              return false;
              }
      
          virtual aabb getbox()const override
              {
              return _p->getbox();
              }
      
      private:
          intersect* _p;
          };
      
      } // rt namespace 
      flip_normal.hpp

       

      /// translate.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10307569.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the translate-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      namespace rt
      {
      
      class translate :public intersect
          {
      public:
          translate(intersect* p, const rtvec& offset);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
          inline const rtvec get_offset()const { return _offset; }
      
          inline void set_offset(const rtvec& f) { _offset = f; }
      
      private:
          intersect* _item;
      
          rtvec _offset;
      
          };
      
      
      
      translate::translate(intersect* p, const rtvec& offset)
          :_item(p)
          , _offset(offset)
          {
          }
      
      bool translate::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          ray movedRay(sight.origin() - _offset, sight.direction(), sight.time());
          if (_item->hit(movedRay, t_min, t_max, info))
              {
              info._p += _offset;
              return true;
              }
          return false;
          }
      
      aabb translate::getbox()const
          {
          aabb box = _item->getbox();
          return aabb(box.min() + _offset, box.max() + _offset);
          }
      
      }// rt namespace
      translate.hpp

       

      /// rotate.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10307569.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the translate-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      
      namespace rt
      {
      
      // the statement of rotate_y class
      
      class rotate_y :public intersect
          {
      public:
          rotate_y(intersect* p, rtvar angle);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
      private:
          intersect* _item;
      
          rtvar _sinθ;
      
          rtvar _cosθ;
      
          aabb _box;
      
          };
      
      // the statement of rotate_x class
      
      class rotate_x :public intersect
          {
      public:
          rotate_x(intersect* p, rtvar angle);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
      private:
          intersect* _item;
      
          rtvar _sinθ;
      
          rtvar _cosθ;
      
          aabb _box;
      
          };
      
      // the statement of rotate_z class
      
      class rotate_z :public intersect
          {
      public:
          rotate_z(intersect* p, rtvar angle);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
      private:
          intersect* _item;
      
          rtvar _sinθ;
      
          rtvar _cosθ;
      
          aabb _box;
      
          };
      
      
      // the implementation of rotate_y class
      
      rotate_y::rotate_y(intersect* p, rtvar angle)
          :_item(p)
          {
          rtvar radians = (π / 180.) * angle;
          _sinθ = sin(radians);
          _cosθ = cos(radians);
          rtvec min(rtInf(), rtInf(), rtInf());
          rtvec max = -min;
          for (int i = 0; i < 2; ++i)
              for (int j = 0; j < 2; ++j)
                  for (int k = 0; k < 2; ++k)
                      {
                      rtvar x = i * _box.max().x() + (1 - i)*_box.min().x();
                      rtvar y = j * _box.max().y() + (1 - j)*_box.min().y();
                      rtvar z = k * _box.max().z() + (1 - k)*_box.min().z();
                      rtvar newx = _cosθ * x + _sinθ * z;
                      rtvar newz = -_sinθ * x + _cosθ * z;
                      rtvec tester(newx, y, newz);
                      for (int c = 0; c < 3; ++c)
                          {
                          if (tester[c] > max[c])
                              max[c] = tester[c];
                          if (tester[c] < min[c])
                              min[c] = tester[c];
                          }
                      }
          _box = aabb(min, max);
          }
      
      bool rotate_y::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvec eye = sight.origin();
          rtvec direction = sight.direction();
          eye[0] = _cosθ * sight.origin()[0] - _sinθ * sight.origin()[2];
          eye[2] = _sinθ * sight.origin()[0] + _cosθ * sight.origin()[2];
          direction[0] = _cosθ * sight.direction()[0] - _sinθ * sight.direction()[2];
          direction[2] = _sinθ * sight.direction()[0] + _cosθ * sight.direction()[2];
          ray rotatedRay(eye, direction, sight.time());
          if (_item->hit(rotatedRay, t_min, t_max, info))
              {
              rtvec p = info._p;
              rtvec n = info._n;
              p[0] = _cosθ * info._p[0] + _sinθ * info._p[2];
              p[2] = -_sinθ * info._p[0] + _cosθ * info._p[2];
              n[0] = _cosθ * info._n[0] + _sinθ * info._n[2];
              n[2] = -_sinθ * info._n[0] + _cosθ * info._n[2];
              info._p = p;
              info._n = n;
              return true;
              }
          return false;
          }
      
      aabb rotate_y::getbox()const
          {
          return _box;
          }
      
      // the implementation of rotate_x class
      
      rotate_x::rotate_x(intersect* p, rtvar angle)
          :_item(p)
          {
          rtvar radians = (π / 180.) * angle;
          _sinθ = sin(radians);
          _cosθ = cos(radians);
          rtvec min(rtInf(), rtInf(), rtInf());
          rtvec max = -min;
          for (int i = 0; i < 2; ++i)
              for (int j = 0; j < 2; ++j)
                  for (int k = 0; k < 2; ++k)
                      {
                      rtvar x = i * _box.max().x() + (1 - i)*_box.min().x();
                      rtvar y = j * _box.max().y() + (1 - j)*_box.min().y();
                      rtvar z = k * _box.max().z() + (1 - k)*_box.min().z();
                      rtvar newy = _cosθ * x - _sinθ * z;
                      rtvar newz = _sinθ * x + _cosθ * z;
                      rtvec tester(x, newy, newz);
                      for (int c = 0; c < 3; ++c)
                          {
                          if (tester[c] > max[c])
                              max[c] = tester[c];
                          if (tester[c] < min[c])
                              min[c] = tester[c];
                          }
                      }
          _box = aabb(min, max);
          }
      
      bool rotate_x::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvec eye = sight.origin();
          rtvec direction = sight.direction();
          eye[1] = _cosθ * sight.origin()[1] + _sinθ * sight.origin()[2];
          eye[2] = -_sinθ * sight.origin()[1] + _cosθ * sight.origin()[2];
          direction[1] = _cosθ * sight.direction()[1] + _sinθ * sight.direction()[2];
          direction[2] = -_sinθ * sight.direction()[1] + _cosθ * sight.direction()[2];
          ray rotatedRay(eye, direction, sight.time());
          if (_item->hit(rotatedRay, t_min, t_max, info))
              {
              rtvec p = info._p;
              rtvec n = info._n;
              p[1] = _cosθ * info._p[1] - _sinθ * info._p[2];
              p[2] = _sinθ * info._p[1] + _cosθ * info._p[2];
              n[1] = _cosθ * info._n[1] - _sinθ * info._n[2];
              n[2] = _sinθ * info._n[1] + _cosθ * info._n[2];
              info._p = p;
              info._n = n;
              return true;
              }
          return false;
          }
      
      aabb rotate_x::getbox()const
          {
          return _box;
          }
      
      
      // the implementation of rotate_z class
      
      rotate_z::rotate_z(intersect* p, rtvar angle)
          :_item(p)
          {
          rtvar radians = (π / 180.) * angle;
          _sinθ = sin(radians);
          _cosθ = cos(radians);
          rtvec min(rtInf(), rtInf(), rtInf());
          rtvec max = -min;
          for (int i = 0; i < 2; ++i)
              for (int j = 0; j < 2; ++j)
                  for (int k = 0; k < 2; ++k)
                      {
                      rtvar x = i * _box.max().x() + (1 - i)*_box.min().x();
                      rtvar y = j * _box.max().y() + (1 - j)*_box.min().y();
                      rtvar z = k * _box.max().z() + (1 - k)*_box.min().z();
                      rtvar newx = _cosθ * x - _sinθ * y;
                      rtvar newy = _sinθ * x + _cosθ * y;
                      rtvec tester(newx, newy, z);
                      for (int c = 0; c < 3; ++c)
                          {
                          if (tester[c] > max[c])
                              max[c] = tester[c];
                          if (tester[c] < min[c])
                              min[c] = tester[c];
                          }
                      }
          _box = aabb(min, max);
          }
      
      bool rotate_z::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvec eye = sight.origin();
          rtvec direction = sight.direction();
          eye[0] = _cosθ * sight.origin()[0] + _sinθ * sight.origin()[1];
          eye[1] = -_sinθ * sight.origin()[0] + _cosθ * sight.origin()[1];
          direction[0] = _cosθ * sight.direction()[0] + _sinθ * sight.direction()[1];
          direction[1] = -_sinθ * sight.direction()[0] + _cosθ * sight.direction()[1];
          ray rotatedRay(eye, direction, sight.time());
          if (_item->hit(rotatedRay, t_min, t_max, info))
              {
              rtvec p = info._p;
              rtvec n = info._n;
              p[0] = _cosθ * info._p[0] - _sinθ * info._p[1];
              p[1] = _sinθ * info._p[0] + _cosθ * info._p[1];
              n[0] = _cosθ * info._n[0] - _sinθ * info._n[1];
              n[1] = _sinθ * info._n[0] + _cosθ * info._n[1];
              info._p = p;
              info._n = n;
              return true;
              }
          return false;
          }
      
      aabb rotate_z::getbox()const
          {
          return _box;
          }
      
      
      } // rt namespace
      rotate.hpp

       

      鑒于這個(gè)系統(tǒng)的變換均針對(duì)運(yùn)算期的每個(gè)點(diǎn)做變換,具體的幾何體不變,所以,造成一個(gè)問題就是不方便獲取變換后的法線等信息,也不利于重置紋理材質(zhì)等,就長(zhǎng)方體而言,比如我想改變某個(gè)面的紋理或者材質(zhì),就很困難,所以新加了很多接口,但是,這些接口都是統(tǒng)一的,所以又重新整了一個(gè)基類,提高代碼重用性和可維護(hù)性

      但我只改了反轉(zhuǎn)向量,沒有對(duì)旋轉(zhuǎn)做適應(yīng)的變動(dòng)

      /// rectangleBasic.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the rectangle-class for the ray-tracing project
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      class rectangle :public intersect
          {
      public:
          rectangle() {  }
      
          rectangle(rtvar u1, rtvar u2, rtvar v1, rtvar v2, rtvar other, material* mat, rtvec nor)
              :_u1(u1)
              , _u2(u2)
              , _v1(v1)
              , _v2(v2)
              , _materialp(mat)
              , _normal(nor)
          {
          }
      
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override = 0;
      
          virtual aabb getbox()const = 0;
      
      public:
          inline const rtvec Getnormal()const { return _normal; }
      
          inline const lvgm::vec2<lvgm::precision> Urange()const { return lvgm::vec2<lvgm::precision>(rtmin(_u1, _u2), rtmax(_u1, _u2)); }
      
          inline const lvgm::vec2<lvgm::precision> Vrange()const { return lvgm::vec2<lvgm::precision>(rtmin(_v1, _v2), rtmax(_v1, _v2)); }
      
          inline const material* Getmaterial()const { return _materialp; }
      
          inline void flipNormal() { _normal = -_normal; }
      
          inline void setmaterial(material* m) { _materialp = m; }
      
          inline void setnormal(const rtvec& n) { _normal = n; }
      
      protected:
          material* _materialp;
      
          rtvar _u1, _u2;
      
          rtvar _v1, _v2;
      
          rtvar _other;
      
          rtvec _normal;
          };
      
      } // rt namespace 
      rectangleBasic.hpp

       

      /// rectangles.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the rectangles-class for the ray-tracing project
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      class rectangles:public rectangle
          {
      public:
          rectangles(rectangle** list, size_t n) :_list(list), _size(n) {  }
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override { return aabb(); }
      
      private:
          rectangle** _list;
      
          size_t _size;
          };
      
      
      
          // the implementation of intersections class
      
      bool rectangles::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          hitInfo t_rec;
          bool hitSomething = false;
          rtvar far = t_max;            //剛開始可以看到無(wú)限遠(yuǎn)
          for (int i = 0; i < _size; ++i)
              {
              if (_list[i]->hit(sight, t_min, far, t_rec))
                  {
                  hitSomething = true;
                  far = t_rec._t;            //將上一次的最近撞擊點(diǎn)作為視線可達(dá)最遠(yuǎn)處
                  info = t_rec;
                  }
              }
          return hitSomething;
          }
      
      }
      rectangles.hpp

       

      /// rectangle.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the rect-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      //the statement of xy_rect class
      
      class xy_rect : public rectangle 
          {
      public:
          xy_rect() {  }
      
          /*
          @brief: the rectangle in the x-y plane
          @param: the boundary of x axis
                  the boundary of y axis
                  the value of z axis
                  the material of rectangle
                  flip normal or not
          */
          xy_rect(rtvar x1, rtvar x2, rtvar y1, rtvar y2, rtvar z0, material* mat, bool _flipNormal = false);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
          };
      
      //the statement of xz_rect class
      
      class xz_rect : public rectangle 
          {
      public:
          xz_rect() {  }
      
          /*
          @brief: the rectangle in the x-z plane
          @param: the boundary of x axis
                  the boundary of z axis
                  the value of y axis
                  the material of rectangle
          */
          xz_rect(rtvar x1, rtvar x2, rtvar z1, rtvar z2, rtvar y0, material* mat, bool _flipNormal = false);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
          };
      
      //the statement of yz_rect class
      
      class yz_rect : public rectangle 
          {
      public:
          yz_rect() {  }
      
          /*
          @brief: the rectangle in the y-z plane
          @param: the boundary of y axis
                  the boundary of z axis
                  the value of x axis
                  the material of rectangle
          */
          yz_rect(rtvar y1, rtvar y2, rtvar z1, rtvar z2, rtvar x0, material* mat, bool _flipNormal = false);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
          };
      
      
      
      // the implementation of xy_rect class
      
      inline xy_rect::xy_rect(rtvar x1, rtvar x2, rtvar y1, rtvar y2, rtvar z0, material* mat, bool _flipNormal)
          : rectangle(x1, x2, y1, y2, z0, mat, rtvec(0., 0., 1.))
          {
          if (_flipNormal)flipNormal();
          }
      
      bool xy_rect::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvar t = (_other - sight.origin().z()) / sight.direction().z();
          if (t < t_min || t > t_max)return false;
      
          rtvar x = sight.origin().x() + t*sight.direction().x();
          rtvar y = sight.origin().y() + t*sight.direction().y();
          if (x < _u1 || x > _u2 || y < _v1 || y > _v2)
              return false;
      
          info._u = (x - _u1) / (_u2 - _u1);
          info._v = (y - _v1) / (_v2 - _v1);
          info._t = t;
          info._materialp = _materialp;
          info._p = sight.go(t);
          info._n = rtvec(0, 0, 1);
      
          return true;
          }
      
      aabb xy_rect::getbox()const
          {
          return aabb(rtvec(_u1, _v1, _other - 0.0001), rtvec(_u2, _v2, _other + 0.0001));
          }
      
      
      // the implementation of xz_rect class
      
      inline xz_rect::xz_rect(rtvar x1, rtvar x2, rtvar z1, rtvar z2, rtvar y0, material* mat, bool _flipNormal)
          : rectangle(x1, x2, z1, z2, y0, mat, rtvec(0., 1., 0.))
          {
          if (_flipNormal)flipNormal();
          }
      
      bool xz_rect::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvar t = (_other - sight.origin().y()) / sight.direction().y();
          if (t < t_min || t > t_max)return false;
      
          rtvar x = sight.origin().x() + t*sight.direction().x();
          rtvar z = sight.origin().z() + t*sight.direction().z();
          if (x < _u1 || x > _u2 || z < _v1 || z > _v2)
              return false;
      
          info._u = (x - _u1) / (_u2 - _u1);
          info._v = (z - _v1) / (_v2 - _v1);
          info._t = t;
          info._materialp = _materialp;
          info._p = sight.go(t);
          info._n = rtvec(0, 1, 0);
      
          return true;
          }
      
      aabb xz_rect::getbox()const
          {
          return aabb(rtvec(_u1, _other - 0.0001, _v1), rtvec(_u2, _other + 0.0001, _v2));
          }
      
      // the implementation of yz_rect class
      
      inline yz_rect::yz_rect(rtvar y1, rtvar y2, rtvar z1, rtvar z2, rtvar x0, material* mat, bool _flipNormal)
          : rectangle(y1, y2, z1, z2, x0, mat, rtvec(1., 0., 0.))
          {
          if (_flipNormal)flipNormal();
          }
      
      bool yz_rect::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          rtvar t = (_other - sight.origin().x()) / sight.direction().x();
          if (t < t_min || t > t_max)return false;
      
          rtvar y = sight.origin().y() + t*sight.direction().y();
          rtvar z = sight.origin().z() + t*sight.direction().z();
          if (y < _u1 || y > _u2 || z < _v1 || z > _v2)
              return false;
      
          info._u = (y - _u1) / (_u2 - _u1);
          info._v = (z - _v1) / (_v2 - _v1);
          info._t = t;
          info._materialp = _materialp;
          info._p = sight.go(t);
          info._n = rtvec(1, 0, 0);
      
          return true;
          }
      
      aabb yz_rect::getbox()const
          {
          return aabb(rtvec(_other - 0.0001, _u1, _v1), rtvec(_other + 0.0001, _u2, _v2));
          }
      
      }// rt namespace 
      rectangle.hpp

       

      /// box.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10307569.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the box-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of box class
      
      class box: public intersect
          {
      public:
          box() {  }
      
          box(const rtvec& pointmin, const rtvec& pointmax, material * mat);
      
          virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const override;
      
          virtual aabb getbox()const override;
      
      public:
          // the normal of xy_rect, the normal's direction is +
          inline const rtvec& xy_n()        const    { return _list[0].Getnormal(); }
      
          // the normal of xy_rect, the normal's direction is -
          inline const rtvec& xy_nflip()    const    { return _list[1].Getnormal(); }
          
          inline const rtvec& xz_n()        const    { return _list[2].Getnormal(); }
      
          inline const rtvec& xz_nflip()    const    { return _list[3].Getnormal(); }
              
          inline const rtvec& yz_n()        const    { return _list[4].Getnormal(); }
      
          inline const rtvec& yz_nflip() const    { return _list[5].Getnormal(); }
      
      
          inline void set_xy_material(material* m) { _list[0].setmaterial(m); }
      
          inline void set_xy_flipmaterial(material* m) { _list[1].setmaterial(m); }
      
          inline void set_xz_material(material* m) { _list[2].setmaterial(m); }
      
          inline void set_xz_flipmaterial(material* m) { _list[3].setmaterial(m); }
      
          inline void set_yz_material(material* m) { _list[4].setmaterial(m); }
      
          inline void set_yz_flipmaterial(material* m) { _list[5].setmaterial(m); }
      
      private:
          rtvec _min;
          
          rtvec _max;
      
          rectangles* _list;
          };
      
      
      
      // the implementation of box class
      
      inline     box::box(const rtvec& pointmin, const rtvec& pointmax, material * mat)
          :_min(pointmin)
          ,_max(pointmax)
          {
          rectangle ** list = new rectangle*[6];
          list[0] = new xy_rect(_min.x(), _max.x(), _min.y(), _max.y(), _max.z(), mat);
          list[1] = new xy_rect(_min.x(), _max.x(), _min.y(), _max.y(), _min.z(), mat, true);
          list[2] = new xz_rect(_min.x(), _max.x(), _min.z(), _max.z(), _max.y(), mat);
          list[3] = new xz_rect(_min.x(), _max.x(), _min.z(), _max.z(), _min.y(), mat, true);
          list[4] = new yz_rect(_min.y(), _max.y(), _min.z(), _max.z(), _max.x(), mat);
          list[5] = new yz_rect(_min.y(), _max.y(), _min.z(), _max.z(), _min.x(), mat, true);
          _list = new rectangles(list, 6);
          }
      
      bool box::hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const
          {
          return _list->hit(sight, t_min, t_max, info);
          }
      
      aabb box::getbox()const
          {
          return aabb(_min, _max);
          }
      
      } // rt namespace 
      box.hpp

       

       material

      /// RTmaterial.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        some materials
      //                diffuse
      //                metal
      //                dielectric
      //                areaLight
      //                isotropic
      // -----------------------------------------------------
      
      #pragma once
      
      
      #include "E:\OpenGL\光線追蹤\code\ray tracing 1-2\ray tracing 1-2\ray.hpp"
      #include "E:\OpenGL\光線追蹤\code\ray tracing 1-2\ray tracing 1-2\include\hit\intersect.hpp"
      #include "material.hpp"
      
      #include "diffuse.hpp"
      #include "metal.hpp"
      #include "dielectric.hpp"
      #include "light.hpp"
      #include "isotropic.hpp"
      RTmaterial.hpp

       

      /// material.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        the material-class for the ray-tracing project
      //                from the 《ray tracing in one week》
      // -----------------------------------------------------
      
      #pragma once
      
      namespace rt
      {
      
      // the statement of material class
      
      class material
          {
      public:
      
          /*
          @brief: produce a scattered ray
          @param: InRay -> Incident light
                  info -> the information of intersect-point(hit-point)
                  attenuation -> when scattered, how much the ray should be attenuated by tis reflectance R
                  scattered -> as we talk, it is a new sight; or
                               it is the scattered ray with the intersect-point
          @retur: the function calculate a scattered ray or not
          */
          virtual bool scatter(const ray& InRay, const hitInfo& info, rtvec& attenuation, ray& scattered)const = 0;
      
      
          /*
          @brief: 自發(fā)光
          @param: 紋理所需信息
          @retur: 紋理像素值
          */
          virtual rtvec emitted(rtvar u, rtvar v, const rtvec& p)const { return rtvec(); }
      
          };
      
      }
      material.hpp

       

      /// diffuse.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10198423.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        one of the materials
      // -----------------------------------------------------
      
      #pragma once
      
      namespace rt
      {
      
      class texture;
      
      // the statement of lambertian class
      
      class lambertian : public material
          {
      public:
          lambertian(texture* _tex);
      
          virtual bool scatter(const ray& rIn, const hitInfo& info, rtvec& attenuation, ray& scattered)const override;
      
      public:
          const texture* get_texture()const { return _albedo; }
      
          void set_texture(texture* tex) { _albedo = tex; }
      
      protected:
      
          texture* _albedo;
          };
      
      
      
      // the implementation of lambertian class
      
      inline lambertian::lambertian(texture* _tex)
          :_albedo(_tex) 
          {
          }
      
      bool lambertian::scatter(const ray& rIn, const hitInfo& info, rtvec& attenuation, ray& scattered)const
          {
          rtvec target = info._p + info._n + lvgm::random_unit_sphere();
          scattered = ray{ info._p, target - info._p };
          attenuation = _albedo->value(info._u, info._v, info._p);
          return true;
          }
      
      } // rt namespace
      diffuse.hpp

       

      /// metal.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10206773.html
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2018.12
      // [brief ]        one of the materials
      // -----------------------------------------------------
      
      #pragma once
      
      namespace rt
      {
      
      // the statement of metal class
      
      class metal :public material
          {
      public:
      
          /*
          @param: f -> Fuzzy index
          */
          metal(texture* a, const rtvar f = 0.);
          
          virtual bool scatter(const ray& rIn, const hitInfo& info, rtvec& attenuation, ray& scattered)const override;
      
      public:
          const texture* get_texture()const { return _albedo; }
      
          const rtvar get_fuzz()const { return _fuzz; }
      
          void set_texture(texture* tex) { _albedo = tex; }
      
          void set_fuzz(const rtvar f) { _fuzz = f; }
          
      protected:
      
          texture* _albedo;
      
          rtvar _fuzz;
          };
      
      
      
      inline metal::metal(texture* a, const rtvar f )
          :_albedo(a)
          {
          if (f < 1 && f >= 0)_fuzz = f;
          else _fuzz = 1;
          }
      
      bool metal::scatter(const ray& rIn, const hitInfo& info, rtvec& attenuation, ray& scattered)const
          {
          rtvec target = reflect(rIn.direction().ret_unitization(), info._n);
          scattered = ray{ info._p, target + _fuzz * lvgm::random_unit_sphere() };
          attenuation = _albedo->value(info._u, info._v, info._p);
          return dot(scattered.direction(), info._n) != 0;
          }
      
      } // rt namespace
      metal.hpp

       

      /// dielectric.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10217719.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        one of the materials
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of dielectric class
      
      class dielectric :public material
          {
          public:
      
              /*
              @param: refractive indices
              */
              dielectric(const rtvar RI) :_RI(RI) {  }
      
              virtual bool scatter(const ray& InRay, const hitInfo& info, rtvec& attenuation, ray& scattered)const override;
      
          public:
              const rtvar get_refIndex()const { return _RI; }
      
              void set_refIndex(rtvar ri) { _RI = ri; }
      
          protected:
              rtvar _RI;
      
              inline rtvar schlick(const rtvar cosine)const;
          };
      
      
      
      // the implementation of dielectric class
      
      bool dielectric::scatter(const ray& InRay, const hitInfo& info, rtvec& attenuation, ray& scattered)const
          {
          rtvec outward_normal;
          rtvec refracted;
          rtvec reflected = reflect(InRay.direction(), info._n);
          rtvar eta;
          rtvar reflect_prob;
          rtvar cos;
          attenuation = rtvec(1., 1., 1.);
      
          if (dot(InRay.direction(), info._n) > 0)
              {
              outward_normal = -info._n;
              eta = _RI;
              cos = _RI * dot(InRay.direction(), info._n) / InRay.direction().normal();
              }
          else
              {
              outward_normal = info._n;
              eta = 1.0 / _RI;
              cos = -dot(InRay.direction(), info._n) / InRay.direction().normal();
              }
      
          if (refract(InRay.direction(), outward_normal, eta, refracted))
              reflect_prob = schlick(cos);    //如果有折射,計(jì)算反射系數(shù)
          else
              reflect_prob = 1.0;        //如果沒有折射,那么為全反射
      
          if (lvgm::rand01() < reflect_prob)
              scattered = ray(info._p, reflected);
          else
              scattered = ray(info._p, refracted);
      
          return true;
          }
      
      inline rtvar dielectric::schlick(const rtvar cosine)const
          {
          rtvar r0 = (1. - _RI) / (1. + _RI);
          r0 *= r0;
          return r0 + (1 - r0)*pow((1 - cosine), 5);
          }
      
      } // rt namespace 
      dielectric.hpp

       

      /// light.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the areaLight-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      
      namespace rt
      {
      
      //the statement of areaLight class
      
      class areaLight :public material
          {
      public:
          areaLight() {  }
      
          areaLight(texture* mat) :_emit(mat) {  }
      
          virtual bool scatter(const ray& InRay, const hitInfo& info, rtvec& attenuation, ray& scattered)const { return false; }
      
          virtual rtvec emitted(rtvar u, rtvar v, const rtvec& p)const { return _emit->value(u, v, p); }
      
      public:
          const texture* get_texture()const { return _emit; }
      
          void set_texture(texture* tex) { _emit = tex; }
      
      private:
          texture* _emit;
          };
      
      } // rt namespace
      light.hpp

       

      /// isotropic.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the isotropic-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
          class isotropic :public material
          {
          public:
              isotropic(texture* tex) :_albedo(tex) {  }
      
              virtual bool scatter(const ray& InRay, const hitInfo& info, rtvec& attenuation, ray& scattered)const override
              {
                  scattered = ray(info._p, lvgm::random_unit_sphere());
                  attenuation = _albedo->value(info._u, info._v, info._p);
                  return true;
              }
      
          public:
              const texture* get_texture()const { return _albedo; }
      
              void set_texture(texture* tex) { _albedo = tex; }
      
          private:
              texture * _albedo;
          };
      
      } // rt namespace
      isotropic.hpp

       

       texture

      /// RTtexture.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        some textures
      //                checker
      //                constant
      //                Perlin noise
      //                image
      // -----------------------------------------------------
      
      #pragma once
      
      
      #include "RTdef.hpp"
      
      #include "texture.hpp"
      
      #include "checker_tex.hpp"
      #include "constant_tex.hpp"
      
      #include "Perlin.hpp"
      #include "noise_tex.hpp"
      
      #include "image_tex.hpp"
      RTtexture.hpp

       

      /// texture.hpp
      
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the texture-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      class texture
          {
      public:
          
          virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const = 0;
          
          };
      
      } // rt namespace
      texture.hpp

       

      /// constant_tex.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10285473.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the constant_texture-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of constant_texture class
          
      class constant_texture :public texture
          {
      public:
      
          constant_texture() {  }
      
          constant_texture(const rtvec& color);
      
          virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override;
      
      public:
      
          inline const rtvec& color()const { return _color; }
      
          inline void set_color(const rtvec& color) { _color = color; }
      
      private:
      
          rtvec _color;
      
          };
      
      
      
      // the implementation of constant_texture class
      
      inline constant_texture::constant_texture(const rtvec& color)
          :_color(color)
          {
          }
      
      rtvec constant_texture::value(rtvar u, rtvar v, const rtvec& p)const
          {
          return _color;
          }
      
      } // rt namesapce 
      constant_texture .hpp

       

      /// checker_tex.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10285473.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the checker_texture-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of checker_texture class
      
      class checker_texture :public texture
          {
          public:
              checker_texture() {  }
      
              /*
              傳入兩個(gè)用于交錯(cuò)的紋理信息
              */
              checker_texture(texture* t1, texture* t2);
      
              virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override;
      
          private:
      
              texture* _even;
      
              texture* _odd;
      
          };
      
      
      
      // the implementation of checker_texture class
      
      inline checker_texture::checker_texture(texture * t1, texture * t2)
              :_even(t1)
              , _odd(t2)
          {
          }
      
      rtvec checker_texture::value(rtvar u, rtvar v, const rtvec& p)const
          {
          rtvar sines = sin(10 * p.x() + 2) * sin(10 * p.y() + 2) * sin(10 * p.z() + 2);
          if (sines < 0)
              return _odd->value(u, v, p);
          else
              return _even->value(u, v, p);
          }
      
      } // rt namespace 
      checker_texture.hpp

       

      /// image_tex.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10295137.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the image_texture-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once 
      
      namespace rt
      {
      
      // the statement of image_texture class
      
      class image_texture: public texture
          {
      public:
          image_texture() {  }
      
          /*
          @param: image -> the rgb list of image texture 
                  a  b  -> the size of image texture
          */
          image_texture(unsigned char* image, size_t a, size_t b);
      
          virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override;
      
      public:
      
          inline unsigned char* image()const    { return _image; }
      
          inline size_t sizeX()const            { return _sizeX; }
      
          inline size_t sizeY()const            { return _sizeY; }
      
      private:
          unsigned char* _image;
      
          size_t _sizeX;
      
          size_t _sizeY;
          };
      
      
      
      //the implementation of image_texture class
      
      image_texture::image_texture(unsigned char* image, size_t a, size_t b)
          :_image(image)
          ,_sizeX(a)
          ,_sizeY(b)
          {
          }
      
      rtvec image_texture::value(rtvar u, rtvar v, const rtvec& p)const
          {
          int i = u*_sizeX;
          int j = (1 - v)*_sizeY - 0.001;
          if (i < 0)i = 0;
          if (j < 0)j = 0;
          if (i > _sizeX - 1)i = _sizeX - 1;
          if (j > _sizeY - 1)j = _sizeY - 1;
          rtvar r = int(_image[3 * i + 3 * _sizeX*j]) / 255.0;
          rtvar g = int(_image[3 * i + 3 * _sizeX*j + 1]) / 255.0;
          rtvar b = int(_image[3 * i + 3 * _sizeX*j + 2]) / 255.0;
          return rtvec(r, g, b);
          }
      
      } // rt namespace 
      image_texture.hpp

       

      /// Perlin.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10291292.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the Perlin-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of Perlin class
      
      class Perlin
          {
      public:
      
          /*
          產(chǎn)生噪聲值
          */
          inline rtvar noise(const rtvec& p)const;
      
          /*
          @brief: 三線性插值
          @param: list -> 輔助數(shù)組
          u v w -> 0~1 的輔助系數(shù)
          @retur: 插值結(jié)果值
          */
          static rtvar perlin_interp(rtvec list[2][2][2], rtvar u, rtvar v, rtvar w);
      
          /*
          對(duì)噪聲值進(jìn)行采樣
          */
          inline rtvar turb(const rtvec& p, int depth) const;
      
          inline rtvec* randomvalue()const { return _randomvalue; }
      
          inline int* perm_x()const { return _perm_x; }
      
          inline int* perm_y()const { return _perm_y; }
      
          inline int* perm_z()const { return _perm_z; }
      
      private:
          static rtvec * _randomvalue;
      
          static int * _perm_x;
      
          static int * _perm_y;
      
          static int * _perm_z;
          };
      
      
      
      // the implement of Perlin class
      
      rtvec * Perlin::_randomvalue = lvgm::random_normalized3D(256);
      
      int * Perlin::_perm_x = lvgm::generate_random0n(256);
      
      int * Perlin::_perm_y = lvgm::generate_random0n(256);
      
      int * Perlin::_perm_z = lvgm::generate_random0n(256);
      
      rtvar Perlin::turb(const rtvec& p, int depth = 7) const 
          {
          rtvar accumulate = 0;
          rtvec t = p;
          rtvar weight = 1.0;
          for (int i = 0; i < depth; i++) 
              {
              accumulate += weight*noise(t);
              weight *= 0.5;
              t *= 2;
              }
          return abs(accumulate);
          }
      
      inline rtvar Perlin::noise(const rtvec& p)const
          {
          int i = floor(p.x());
          int j = floor(p.y());
          int k = floor(p.z());
          rtvar u = p.x() - i;
          rtvar v = p.y() - j;
          rtvar w = p.z() - k;
      
          rtvec list[2][2][2];
          for (int a = 0; a < 2; ++a)
              for (int b = 0; b < 2; ++b)
                  for (int c = 0; c < 2; ++c)
                      {
                      list[a][b][c] = _randomvalue[_perm_x[(i + a) & 255] ^ _perm_y[(j + b) & 255] ^ _perm_z[(k + c) & 255]];
      #ifdef listtest
                      if (list[a][b][c].x() < 0)stds cout << "list.x < 0 " << stds endl;
                      if (list[a][b][c].y() < 0)stds cout << "list.y < 0 " << stds endl;
                      if (list[a][b][c].z() < 0)stds cout << "list.z < 0 " << stds endl;
      #endif
                      }
          return perlin_interp(list, u, v, w);
          }
      
      rtvar Perlin::perlin_interp(rtvec list[2][2][2], rtvar u, rtvar v, rtvar w)
          {
      #ifdef uvwtest
          if (u < 0)stds cout << "u < 0 " << stds endl;
          if (v < 0)stds cout << "v < 0 " << stds endl;
          if (w < 0)stds cout << "w < 0 " << stds endl;
          if (u > 1)stds cout << "u > 1 " << stds endl;
          if (v > 1)stds cout << "v > 1 " << stds endl;
          if (w > 1)stds cout << "w > 1 " << stds endl;
      #endif
          rtvar uu = u*u*(3 - 2 * u);
          rtvar vv = u*v*(3 - 2 * v);
          rtvar ww = u*w*(3 - 2 * w);
      
          rtvar accumulate = 0;
          for (int i = 0; i < 2; ++i)
              for (int j = 0; j < 2; ++j)
                  for (int k = 0; k < 2; ++k)
                      {
                      rtvec weight(u - i, v - j, w - k);
                      accumulate +=
                          (i*uu + (1 - i) * (1 - uu))*
                          (j*vv + (1 - j) * (1 - vv))*
                          (k*ww + (1 - k) * (1 - ww))*
                          lvgm::dot(list[i][j][k], weight);
      #ifdef accumulatetest
                      if (accumulate < 0)stds cout << "accumulate < 0 " << stds endl;
      #endif
                      }
          return accumulate;        
          }
      
      } // rt namespace 
      Perlin.hpp

       

      /// noise_tex.hpp
      // http://www.rzrgm.cn/lv-anchoret/p/10291292.html
      // -----------------------------------------------------
      // [author]        lv
      // [begin ]        2019.1
      // [brief ]        the noise_texture-class for the ray-tracing project
      //                from the 《ray tracing the next week》
      // -----------------------------------------------------
      
      #pragma once
      
      
      namespace rt
      {
      
      // the statement of noise_texture class
      
      class noise_texture :public texture
          {
      public:
          noise_texture() {  }
      
          noise_texture(const rtvar scale);    
      
          virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override;
      
          inline const rtvar get_scale()const { return _scale; }
      
          inline void set_scale(const rtvar s) { _scale = s; }
          
      private:
          Perlin _noise;
      
          rtvar _scale;
          };
      
      
      
      // the implementation of noise_texture class
      
      noise_texture::noise_texture(const rtvar scale)
          :_scale(scale)
          {
          }
      
      rtvec noise_texture::value(rtvar u, rtvar v, const rtvec& p)const
          {
          return rtvec(1., 1., 1.) * 0.5 * (1 + sin(_scale * p.z() + 10 * _noise.noise(p)));
          }
      
      } // rt namespace 
      noise_texture.hpp

       

      如果有什么問題可以留言

       

      posted @ 2019-01-27 18:02  林-兮  閱讀(1032)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 天堂a无码a无线孕交| 亚洲人成电影网站 久久影视| 国产精品一二三中文字幕| 一区二区三区不卡国产| 九九热在线观看视频精品| 中国老太婆video| 九九热精品在线观看| 婷婷六月天在线| 亚洲一区二区三区蜜桃臀| 日本中文字幕久久网站| 公主岭市| 国产精品国产精品一区精品| 国产亚洲精品第一综合另类无码无遮挡又大又爽又黄的视频 | 国产线播放免费人成视频播放| 人人妻人人做人人爽夜欢视频 | 最近日本免费观看高清视频| 亚洲精品久久无码av片软件| 精品亚洲国产成人av在线| 亚洲男人的天堂在线观看| 午夜福利高清在线观看| 高级艳妇交换俱乐部小说| 亚洲熟女乱色一区二区三区 | 久久精品熟女亚洲av艳妇| 麻豆国产成人AV在线播放| 国产精品久久久久影院| 国内揄拍国内精品对久久| 国产精品亚洲二区亚瑟| 无套中出极品少妇白浆| 国产福利深夜在线播放| 国产成人亚洲日韩欧美| 亚洲精品久荜中文字幕| 亚洲欧美日本久久网站| 国产一区二区不卡在线| 精品人妻一区二区三区四区在线 | 久久亚洲精品11p| 亚洲电影天堂在线国语对白| 古蔺县| 中文国产人精品久久蜜桃| 天堂V亚洲国产V第一次| 水富县| 漂亮人妻被强中文字幕久久|