// File: srajangarg[P]raytracer/src/main.cpp
// Function: getShadedColor(Primitive const&, Vec3 const&, Ray const&)
RGB
getShadedColor(Primitive const & primitive, Vec3 const & pos, Ray const & ray)
{
  RGB amb(0, 0, 0), lamb(0, 0, 0), spec(0, 0, 0);
  RGB C(primitive.getColor()), S, I;
  Vec3 r, u, n, i;
  bool use_dist;

  double ma = primitive.getMaterial().getMA();
  double ms = primitive.getMaterial().getMS();
  double ml = primitive.getMaterial().getML();
  double msp = primitive.getMaterial().getMSP();
  double msm = primitive.getMaterial().getMSM();
  double reach_light, ratio = 0, trans;
  
  // ambient component : Ma * C * A
  amb = ma * C * world->getAmbientLightColor();
  
  for (auto it = world->lightsBegin(); it != world->lightsEnd(); it++)
  {  
    trans = 1;
    auto light = *it;
    vector<Ray> shadows = light->getShadowRays(pos, use_dist);
    reach_light = shadows.size();

    // iterate over shadows
    for (auto shadow : shadows)
    {
      auto inter = world->intersect(shadow);

      if (inter != NULL) {
        // if the light is passing through a transparent object, consider it
        if (inter->getMaterial().getMT() > 0)
            trans = inter->getMaterial().getMT();
        // else decrease the number of shadow rays reaching the object
        else if (not use_dist or (shadow.minT() > 0 and shadow.minT() < 1))
            reach_light--;
      }
    }

    // how many shadow rays did not collide
    ratio = reach_light / (double) shadows.size();
    // if none of them passed thorugh, skip lambertian and specular
    if (ratio < EPS)
      continue;

    // normal and incidence vectors, light color
    n = primitive.calculateNormal(pos);
    i = light->getIncidenceVector(pos);
    I = light->getColor(pos);

    // lambertian component : Ml * C * I * max(i.n, 0)
    lamb += trans * ratio * ml * C * I * std::max(i * n, (double)0);

    // S                    : Msm * C + (1-Msm) * RBG(1, 1, 1)  
    // r                    : 2(i.n)n  - i   
    S = msm * C + (1 - msm) * RGB(1, 1, 1); 
    r = 2*((i * n) * n) - i;
    u = ray.direction();
    u.normalize();

    // specular component   : Ms * S * I * (max(-r.u, 0))^Msp                 
    spec += trans * ratio * ms * S * I * pow(std::max(-r*u, (double)0), msp);
  }

  return amb + spec + lamb;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4b0, %rsp            # imm = 0x4B0
movq %rdi, -0x430(%rbp)
movq %rdi, %rax
movq %rax, -0x428(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
leaq -0x38(%rbp), %rdi
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x9640
leaq -0x50(%rbp), %rdi
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x9640
leaq -0x68(%rbp), %rdi
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x9640
movq -0x10(%rbp), %rdi
callq 0x42ca0
movq %rax, %rsi
leaq -0x80(%rbp), %rdi
callq 0x9680
leaq -0x98(%rbp), %rdi
callq 0x3bce0
leaq -0xb0(%rbp), %rdi
callq 0x3bce0
leaq -0xc8(%rbp), %rdi
callq 0x6fc0
leaq -0xe0(%rbp), %rdi
callq 0x6fc0
leaq -0xf8(%rbp), %rdi
callq 0x6fc0
leaq -0x110(%rbp), %rdi
callq 0x6fc0
movq -0x10(%rbp), %rdi
callq 0x42cc0
movq %rax, %rdi
callq 0x42ce0
movsd %xmm0, -0x120(%rbp)
movq -0x10(%rbp), %rdi
callq 0x42cc0
movq %rax, %rdi
callq 0x42d00
movsd %xmm0, -0x128(%rbp)
movq -0x10(%rbp), %rdi
callq 0x42cc0
movq %rax, %rdi
callq 0x42d20
movsd %xmm0, -0x130(%rbp)
movq -0x10(%rbp), %rdi
callq 0x42cc0
movq %rax, %rdi
callq 0x42d40
movsd %xmm0, -0x138(%rbp)
movq -0x10(%rbp), %rdi
callq 0x42cc0
movq %rax, %rdi
callq 0x42d60
movsd %xmm0, -0x140(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x150(%rbp)
movsd -0x120(%rbp), %xmm0
leaq -0x188(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x42de0
movq 0x1bf32(%rip), %rsi     # 0x5cdf8
leaq -0x1a0(%rbp), %rdi
callq 0x3f6d0
leaq -0x170(%rbp), %rdi
leaq -0x188(%rbp), %rsi
leaq -0x1a0(%rbp), %rdx
callq 0x42d80
leaq -0x38(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x96c0
movq 0x1bef5(%rip), %rdi     # 0x5cdf8
callq 0x42e20
movq %rax, -0x1a8(%rbp)
movq 0x1bee2(%rip), %rdi     # 0x5cdf8
callq 0x42e90
movq %rax, -0x1b0(%rbp)
leaq -0x1a8(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x42e50
testb $0x1, %al
jne 0x40f3e
jmp 0x41608
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x158(%rbp)
leaq -0x1a8(%rbp), %rdi
callq 0x42ec0
movq (%rax), %rax
movq %rax, -0x1b8(%rbp)
movq -0x1b8(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq (%rsi), %rax
movq 0x28(%rax), %rax
leaq -0x1d0(%rbp), %rdi
movq %rdi, -0x438(%rbp)
leaq -0x111(%rbp), %rcx
callq *%rax
movq -0x438(%rbp), %rdi
callq 0x3d0e0
movq %rax, %xmm0
movaps 0x7e1a(%rip), %xmm1     # 0x48dc0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x7e1e(%rip), %xmm1     # 0x48dd0
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x148(%rbp)
leaq -0x1d0(%rbp), %rax
movq %rax, -0x1d8(%rbp)
movq -0x1d8(%rbp), %rdi
callq 0x3cff0
movq %rax, -0x1e0(%rbp)
movq -0x1d8(%rbp), %rdi
callq 0x3ce30
movq %rax, -0x1e8(%rbp)
leaq -0x1e0(%rbp), %rdi
leaq -0x1e8(%rbp), %rsi
callq 0x42ee0
testb $0x1, %al
jne 0x41019
jmp 0x41198
leaq -0x1e0(%rbp), %rdi
callq 0x3d190
movq %rax, %rsi
leaq -0x228(%rbp), %rdi
callq 0x3c940
jmp 0x41036
movq 0x1bdbb(%rip), %rdi     # 0x5cdf8
leaq -0x228(%rbp), %rsi
callq 0x3f5a0
movq %rax, -0x440(%rbp)
jmp 0x41052
movq -0x440(%rbp), %rax
movq %rax, -0x240(%rbp)
cmpq $0x0, -0x240(%rbp)
je 0x41185
movq -0x240(%rbp), %rdi
callq 0x42cc0
movq %rax, -0x448(%rbp)
jmp 0x41083
movq -0x448(%rbp), %rdi
callq 0x42f20
movsd %xmm0, -0x450(%rbp)
jmp 0x41099
movsd -0x450(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x4110d
movq -0x240(%rbp), %rdi
callq 0x42cc0
movq %rax, -0x458(%rbp)
jmp 0x410bf
movq -0x458(%rbp), %rdi
callq 0x42f20
movsd %xmm0, -0x460(%rbp)
jmp 0x410d5
movsd -0x460(%rbp), %xmm0
movsd %xmm0, -0x158(%rbp)
jmp 0x41183
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x230(%rbp)
movl %eax, -0x234(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x3bf20
jmp 0x41643
testb $0x1, -0x111(%rbp)
je 0x41169
leaq -0x228(%rbp), %rdi
callq 0x3e310
movsd %xmm0, -0x468(%rbp)
jmp 0x4112c
movsd -0x468(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x41181
leaq -0x228(%rbp), %rdi
callq 0x3e310
movsd %xmm0, -0x470(%rbp)
jmp 0x41153
movsd -0x470(%rbp), %xmm1
movsd 0x5fd5(%rip), %xmm0     # 0x47138
ucomisd %xmm1, %xmm0
jbe 0x41181
movsd 0x603f(%rip), %xmm0     # 0x471b0
addsd -0x148(%rbp), %xmm0
movsd %xmm0, -0x148(%rbp)
jmp 0x41183
jmp 0x41185
jmp 0x41187
leaq -0x1e0(%rbp), %rdi
callq 0x42f40
jmp 0x40ffd
movsd -0x148(%rbp), %xmm0
movsd %xmm0, -0x478(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x3d0e0
movsd -0x478(%rbp), %xmm0
movq %rax, %xmm1
movaps 0x7bf8(%rip), %xmm2     # 0x48dc0
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x7bfc(%rip), %xmm2     # 0x48dd0
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x150(%rbp)
movsd 0x7bb1(%rip), %xmm0     # 0x48da8
ucomisd -0x150(%rbp), %xmm0
jbe 0x41210
movl $0x4, -0x244(%rbp)
jmp 0x415d2
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq (%rsi), %rax
movq 0x18(%rax), %rax
leaq -0x260(%rbp), %rdi
callq *%rax
jmp 0x4122a
leaq -0xf8(%rbp), %rdi
leaq -0x260(%rbp), %rsi
callq 0x72d0
jmp 0x4123f
movq -0x1b8(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq (%rsi), %rax
movq 0x20(%rax), %rax
leaq -0x278(%rbp), %rdi
callq *%rax
jmp 0x4125c
leaq -0x110(%rbp), %rdi
leaq -0x278(%rbp), %rsi
callq 0x72d0
jmp 0x41271
movq -0x1b8(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq (%rsi), %rax
movq 0x18(%rax), %rax
leaq -0x290(%rbp), %rdi
callq *%rax
jmp 0x4128e
leaq -0xb0(%rbp), %rdi
leaq -0x290(%rbp), %rsi
callq 0x96c0
jmp 0x412a3
movsd -0x158(%rbp), %xmm0
movsd -0x150(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd -0x130(%rbp), %xmm1
mulsd %xmm1, %xmm0
leaq -0x2d8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x42de0
jmp 0x412d5
leaq -0x2c0(%rbp), %rdi
leaq -0x2d8(%rbp), %rsi
leaq -0xb0(%rbp), %rdx
callq 0x42d80
jmp 0x412f1
leaq -0x110(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x3e2b0
movsd %xmm0, -0x480(%rbp)
jmp 0x4130e
movsd -0x480(%rbp), %xmm0
movsd %xmm0, -0x2e0(%rbp)
movq $0x0, -0x2e8(%rbp)
leaq -0x2e0(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
callq 0x3b040
movq %rax, -0x488(%rbp)
jmp 0x41345
movq -0x488(%rbp), %rax
movsd (%rax), %xmm0
leaq -0x2a8(%rbp), %rdi
leaq -0x2c0(%rbp), %rsi
callq 0x42f60
jmp 0x41365
leaq -0x50(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
callq 0x42fc0
jmp 0x41377
movsd -0x140(%rbp), %xmm0
leaq -0x318(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x42de0
jmp 0x41391
movsd -0x140(%rbp), %xmm1
movsd 0x5d97(%rip), %xmm2     # 0x47138
movaps %xmm2, %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0x490(%rbp)
leaq -0x348(%rbp), %rdi
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x9640
jmp 0x413c4
movsd -0x490(%rbp), %xmm0
leaq -0x330(%rbp), %rdi
leaq -0x348(%rbp), %rsi
callq 0x42de0
jmp 0x413e1
leaq -0x300(%rbp), %rdi
leaq -0x318(%rbp), %rsi
leaq -0x330(%rbp), %rdx
callq 0x43010
jmp 0x413fd
leaq -0x98(%rbp), %rdi
leaq -0x300(%rbp), %rsi
callq 0x96c0
jmp 0x41412
leaq -0x110(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x3e2b0
movsd %xmm0, -0x498(%rbp)
jmp 0x4142f
movsd -0x498(%rbp), %xmm0
leaq -0x390(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x3ea20
jmp 0x4144c
leaq -0x378(%rbp), %rdi
movsd 0x6505(%rip), %xmm0     # 0x47960
leaq -0x390(%rbp), %rsi
callq 0x3ea20
jmp 0x41469
leaq -0x360(%rbp), %rdi
leaq -0x378(%rbp), %rsi
leaq -0x110(%rbp), %rdx
callq 0x3bd80
jmp 0x41485
leaq -0xc8(%rbp), %rdi
leaq -0x360(%rbp), %rsi
callq 0x72d0
jmp 0x4149a
movq -0x20(%rbp), %rdi
callq 0x3e290
movq %rax, -0x4a0(%rbp)
jmp 0x414ac
movq -0x4a0(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
callq 0x72d0
jmp 0x414c1
leaq -0xe0(%rbp), %rdi
callq 0x14e00
jmp 0x414cf
movsd -0x158(%rbp), %xmm0
movsd -0x150(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd -0x128(%rbp), %xmm1
mulsd %xmm1, %xmm0
leaq -0x3d8(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x42de0
jmp 0x41504
leaq -0x3c0(%rbp), %rdi
leaq -0x3d8(%rbp), %rsi
leaq -0xb0(%rbp), %rdx
callq 0x42d80
jmp 0x41520
leaq -0x3f8(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x3c030
jmp 0x41535
leaq -0x3f8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x3e2b0
movsd %xmm0, -0x4a8(%rbp)
jmp 0x41552
movsd -0x4a8(%rbp), %xmm0
movsd %xmm0, -0x3e0(%rbp)
movq $0x0, -0x400(%rbp)
leaq -0x3e0(%rbp), %rdi
leaq -0x400(%rbp), %rsi
callq 0x3b040
movq %rax, -0x4b0(%rbp)
jmp 0x41589
movq -0x4b0(%rbp), %rax
movsd (%rax), %xmm0
movsd -0x138(%rbp), %xmm1
callq 0x5710
leaq -0x3a8(%rbp), %rdi
leaq -0x3c0(%rbp), %rsi
callq 0x42f60
jmp 0x415b6
leaq -0x68(%rbp), %rdi
leaq -0x3a8(%rbp), %rsi
callq 0x42fc0
jmp 0x415c8
movl $0x0, -0x244(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x3bf20
movl -0x244(%rbp), %eax
testl %eax, %eax
je 0x415ec
jmp 0x415ea
jmp 0x415ee
jmp 0x415ee
leaq -0x1a8(%rbp), %rdi
xorl %esi, %esi
callq 0x43070
movq %rax, -0x408(%rbp)
jmp 0x40f0f
leaq -0x420(%rbp), %rdi
leaq -0x38(%rbp), %rsi
leaq -0x68(%rbp), %rdx
callq 0x43010
movq -0x430(%rbp), %rdi
leaq -0x420(%rbp), %rsi
leaq -0x50(%rbp), %rdx
callq 0x43010
movq -0x428(%rbp), %rax
addq $0x4b0, %rsp            # imm = 0x4B0
popq %rbp
retq
movq -0x230(%rbp), %rdi
callq 0x5720
nop