
import sys
from math import *

print """
<scene>

  <!--
      Test scene that illuminates a set of reflective plates
      from spherical luminaires of a range of sizes.  This file
      is generated by the Python script plates.py, so for major
      changes it's best to edit that file instead.
    -->

  <image>
    360 240
  </image>

  <sampler type="JitteredSampler">
    <numSamplesU>20</numSamplesU>
    <numSamplesV>20</numSamplesV>
  </sampler>
<!--
  <sampler type="IndependentSampler">
    <numSamples>100</numSamples>
  </sampler>
-->
  <renderer type="DirectOnlyRenderer">
    <!--directIlluminator type="ProjSolidAngleIlluminator" /-->
    <!--directIlluminator type="BRDFIlluminator" /-->
    <!--directIlluminator type="LuminairesIlluminator" /-->
    <directIlluminator type="MultipleIlluminator" />
  </renderer>
  
  <material name="blue" type="Homogeneous">
    <brdf type="Lambertian">
      <reflectance>0.2 0.4 0.8</reflectance>
    </brdf>
  </material>
  
  <material name="grey" type="Homogeneous">
    <brdf type="Lambertian">
      <reflectance>0.4 0.4 0.4</reflectance>
    </brdf>
  </material>
"""

# The lights are at z = y = 0.  There are four of them.

light_spacing = 2.5
light_radii = [0.0333, 0.1, 0.3, 0.9]
light_radiances = map(lambda x: 1 / (x*x), light_radii)

for i in range(4):
    x = (i - 1.5) * light_spacing
    r = light_radii[i]
    L = light_radiances[i]
    print """
      <surface type="Sphere">    
        <material type="LambertianEmitter">
          <radiance>%(L)g %(L)g %(L)g</radiance>
        </material>
        <center>%(x)g 0 0</center>
        <radius>%(r)g</radius>
      </surface>
    """ % locals()
    
# The camera is at z = z_c, y = y_c.

z_c = 15.0
y_c = 2.0

# The distance to the camera, and an ONB with u pointing at the camera

d_c = sqrt(z_c*z_c + y_c*y_c)
z_u = z_c / d_c
y_u = y_c / d_c
z_v = -y_u
y_v = z_u

print """
  <camera>
    <eye>0 %(y_c)g %(z_c)g</eye>
    <target>0 -2 2.5</target>
    <up>0 1 0</up>
    <yFOV>28</yFOV>
  </camera>
""" % locals()

# For the plates to reflect the lights, they have to be tangent
#   to an ellipse that has these two foci.  If 2A is the major
#   axis then the semi-minor axis B can be computed from that.

A = 0.6 * d_c
B = sqrt(A*A - d_c*d_c/4)

# The easy way to generate the plate centers and normals is to
#   transform points and their tangents from a circle to our
#   ellipse.  Some fiddling may be required to get the spacing
#   nice.

plate_thetas = map(lambda t: t * pi/180, [208, 219, 230, 240])
plate_sigmas = [0.005, 0.02, 0.05, 0.1]

# Here are the half width and half length of a plate

plate_width = 0.5
plate_length = 4

y_min = 0;

for i in range(4):
    
    t = plate_thetas[i]
    sigma = plate_sigmas[i]
    
    # plate center point
    z_p = z_c/2 + A * cos(t) * z_u + B * sin(t) * z_v
    y_p = y_c/2 + A * cos(t) * y_u + B * sin(t) * y_v

    # tangent to plate in yz plane
    dz = -A * sin(t) * z_u + B * cos(t) * z_v
    dy = -A * sin(t) * y_u + B * cos(t) * y_v
    l = sqrt(dz*dz + dy*dy)
    dz = dz / l
    dy = dy / l

    # lower edge of plate (from camera's viewpoint)
    z0 = z_p + plate_width * dz
    y0 = y_p + plate_width * dy
    z1 = z_p - plate_width * dz
    y1 = y_p - plate_width * dy

    y_min = min(y0, y1, y_min)
    
    # The four corners of the plate  are at (+/- l, y0, z0)
    #   and (+/- l, y1, z1)
    
    print """
      <material name="ufacet%(i)d" type="Homogeneous">
        <brdf type="Microfacet">
          <diffuseReflectance>0.07 0.09 0.13</diffuseReflectance>
          <n>2</n>
          <alpha_b>%(sigma)g</alpha_b>
        </brdf>
      </material>
      <surface type="Triangle">
        <material ref="ufacet%(i)d" />
        <v0>%(plate_length)g %(y0)g %(z0)g</v0>
        <v1>%(plate_length)g %(y1)g %(z1)g</v1>
        <v2>-%(plate_length)g %(y1)g %(z1)g</v2>
      </surface>
      <surface type="Triangle">
        <material ref="ufacet%(i)d" />
        <v0>-%(plate_length)g %(y1)g %(z1)g</v0>
        <v1>-%(plate_length)g %(y0)g %(z0)g</v1>
        <v2>%(plate_length)g %(y0)g %(z0)g</v2>
      </surface>
    """ % locals()

# A floor a bit below the tiles

y_floor = y_min - 0.15

print """
  <surface type="Triangle">
    <material ref="grey" />
      <v0>-100 %(y_floor)g -100</v0>
      <v1>-100 %(y_floor)g  100</v1>
      <v2> 100 %(y_floor)g  100</v2>
  </surface>
  <surface type="Triangle">
    <material ref="grey" />
      <v0> 100 %(y_floor)g  100</v0>
      <v1> 100 %(y_floor)g -100</v1>
      <v2>-100 %(y_floor)g -100</v2>
  </surface>
""" % locals()
  

# A wall a bit behind the tiles

z_wall = -2

print """
  <surface type="Triangle">
    <material ref="grey" />
      <v0>-100 -100 %(z_wall)g</v0>
      <v1> 100 -100 %(z_wall)g</v1>
      <v2> 100  100 %(z_wall)g</v2>
  </surface>
  <surface type="Triangle">
    <material ref="grey" />
      <v0> 100  100 %(z_wall)g</v0>
      <v1>-100  100 %(z_wall)g</v1>
      <v2>-100 -100 %(z_wall)g</v2>
  </surface>
""" % locals()
  
print """
  <surface type="Sphere">    
    <material type="LambertianEmitter">
      <radiance>800 800 800</radiance>
    </material>
    <center>10 10 4</center>
    <radius>0.5</radius>
  </surface>
    
  <!--background type="Uniform">
    <radiance>0.5 0.5 0.5</radiance>
  </background-->

</scene>
"""
