title: Getting the normal of a cone - Raytracing
body: <p>I'm writing a raytracer in C and I'm having trouble perfecting the shadows on my cone. I think the problem I have is in the calculation of the normal of the cone at the intersection point. <a href="https://i.stack.imgur.com/niluy.png" rel="nofollow noreferrer">Here</a> is a rendering of what I currently have.</p>
  
  <p>The scene described as follows: </p>
  
  <pre><code>resolution: 500, 500
  scene:
  {
      light:
      {
          position: 0, -10, -40
          intensity: 20000
          color: white
      }
      camera:
      {
          position: -5, -7, -40
          direction: 0, 0, 1
          fov: 50
      }
      plane: 
      {
          position: 0, 0, 0
          direction: 0, 0, 1
          color: white
      }
      cone:
      {
          position: 0, 0, -2.5
          direction: -5, -8, 0
          color: white
          radius: 5
          height: 20
      }
      cylinder:
      {
          position: 10, 0, 0
          direction: -5, -8, 0
          color: white
          radius: 5
          height: 20
      }
  }
  </code></pre>
  
  <p>Note that the light is between the objects and the camera.
  The issue there is that I think the cone should be more illuminated, at least, in some areas, as illuminated as the cylinder to the right.</p>
  
  <p>I calculated the normal based on <a href="https://stackoverflow.com/questions/13792861/surface-normal-to-a-cone">this post's answer</a> as follows:</p>
  
  <pre><code>static void get_cone_normal(t_raytracing_tools *r, t_ray *ray, t_object *obj)
  {
      //nhit is the normal at hit point.
      ray-&gt;nhit.x = (ray-&gt;hit.x - obj-&gt;pos.x) * (obj-&gt;height / obj-&gt;rad);
      ray-&gt;nhit.y = obj-&gt;rad / obj-&gt;height;
      ray-&gt;nhit.z = (ray-&gt;hit.z - obj-&gt;pos.z) * (obj-&gt;height / obj-&gt;rad);
      ray-&gt;nhit = v_norm(ray-&gt;nhit);
  }
  </code></pre>
  
  <p>I also thought of the direction of the normal depending on what side of the cone is hit by the ray. After I solve the quadratic equation and get two potential answers, I test each one to figure out if it is within my finite cone (parametric equation is for infinite cone) and according to how the ray hits the cone, I have an int variable n_dir which is either 1 or -1 which I use to invert the normal if the ray hits the inside of the cone. Here is the code for that part:</p>
  
  <pre><code> bool       get_finite_cone_intersection(t_raytracing_tools *r, t_ray *ray, t_object *obj, t_intersection_tools *i)
  {
      bool    r1_too_low;
      bool    r1_too_high;
      bool    r2_too_low;
      bool    r2_too_high;
  
      //i-&gt;r1 and i-&gt;r2 are the two roots (solutions of quadratic eq.)
      r1_too_low = lower_than_min(i-&gt;r1, i, obj, ray);
      r1_too_high = higher_than_max(i-&gt;r1, i, obj, ray);
      r2_too_low = lower_than_min(i-&gt;r2, i, obj, ray);
      r2_too_high = higher_than_max(i-&gt;r2, i, obj, ray);
      if (r1_too_low)
      {
          i-&gt;r1 = NAN; //I set roots to NAN if they are not valid solutions
          if (r2_too_low || r2_too_high)
              i-&gt;r2 = NAN;
          else
              i-&gt;n_dir = 1;
      }
      else if (r1_too_high)
      {
          i-&gt;r1 = NAN;
          if (r2_too_low || r2_too_high)
              i-&gt;r2 = NAN;
          else
              i-&gt;n_dir = -1;
      }
      else if (!r1_too_low &amp;&amp; !r1_too_high)
      {
          i-&gt;r2 = NAN;
          if (r2_too_low)
              i-&gt;n_dir = -1;
          else
              i-&gt;n_dir = 1;
      }
      return (true);
  }
  
  bool        lower_than_min(double r, t_intersection_tools *i, t_object *obj, t_ray *ray)
  {
      if (r &gt; 0)
      {
          if (v_dot(obj-&gt;dir, v_sub(v_add(ray-&gt;origin, v_scale(ray-&gt;dir, r)), obj-&gt;pos)) &lt; 0.0)
              return (true);      
      }
      return (false);
  }
  bool        higher_than_max(double r, t_intersection_tools *i, t_object *obj, t_ray *ray)
  {
      if (r &gt; 0)
      {
          if (v_dot(obj-&gt;dir, v_sub(v_add(ray-&gt;origin, v_scale(ray-&gt;dir, r)),
              v_add(obj-&gt;pos, v_scale(obj-&gt;dir, obj-&gt;height)))) &gt; 0.0)
              return (true);      
      }
      return (false);
  }
  </code></pre>
  
  <p>Also, what the heck, here's the code for my cone intersection:</p>
  
  <pre><code>    bool        get_cone_intersection(t_raytracing_tools *r, t_ray *ray, t_object *cone)
  {
      t_intersection_tools i;
      t_vec3    ori_cen;
      double    k;
      int         n_dir;
  
      i.n_dir = 1;
      k = tan(cone-&gt;angle);
      ori_cen = v_sub(ray-&gt;origin, cone-&gt;pos);
      i.q.x = v_dot(ray-&gt;dir, ray-&gt;dir) - (1.0 + k * k) * powf(v_dot(ray-&gt;dir, cone-&gt;dir), 2.0);
      i.q.y = 2 * (v_dot(ray-&gt;dir, ori_cen) - (1.0 + k * k) * v_dot(ray-&gt;dir, cone-&gt;dir)
                  * v_dot(ori_cen, cone-&gt;dir));
      i.q.z = v_dot(ori_cen, ori_cen) - (1.0 + k * k) * powf(v_dot(ori_cen,
                  cone-&gt;dir), 2.0);
      if (!solve_quadratic(i.q, &amp;i.r1, &amp;i.r2))
          return (0);
      (i.r2 &lt; i.r1) ? ft_swapd(&amp;i.r1, &amp;i.r2) : 0;
      get_finite_cone_intersection(r, ray, cone, &amp;i);
      if (i.r1 &lt; 0 || isnan(i.r1)) //the smallest one is negative, thus take the other one
      {
          i.r1 = i.r2;
      }
      if (i.r1 &lt; 0 || isnan(i.r1))    
          return (false);
      if (r-&gt;t &gt; i.r1)
      {
          ray-&gt;t = i.r1;
          if (ray-&gt;type == R_PRIMARY)
          {
              ray-&gt;hit_obj = cone;
              ray-&gt;hit_type = T_CONE;
              ray-&gt;n_dir = i.n_dir;
          }
      }
      return (true);
  }
  </code></pre>
  
  <p>Hope that's not too much info at once! Again, would love it if someone could shed some light (haha) on the situation. </p>