#! /usr/bin/env python

from lightflowPM import *

s = scene()

# Specify some rendering settings. These values are used by
# all the built-in types, so they are grouped under a unique
# interface, named "default".
s.newInterface( "default", [ "trace-depth", 5, "lighting-depth", 3 ] )

# Make a bright, bright light to model the sun.
s.lightOn( s.newLight( "point", [ "position", vector3( 0, 900, 100 ), "color", vector3( 60000.0, 60000.0, 60000.0 ) ] ) )


# Model the water waves with a fractal pattern.
s.transformBegin( transform().scaling( vector3( 10, 5, 5 ) ) )

waterbumps = s.newPattern( "multifractal",
    [ "basis", "sin",
      "scale", 2.0,
      "depth", 0.1,
      "turbulence.distortion", 1.0,
      "turbulence.omega", 0.1, 0.3,
      "turbulence.lambda", 2.0,
      "turbulence.octaves", 5 ] )

# the "basis" value describes the fractal basis, that here is set to
# "sin", as waves have a sinusoidal origin. 
# "scale" represents the width of the waves. This factor is then
# multiplied by the scaling transform we put before. 
# "depth" represents the depth of the waves, when used to displace a
# surface. 
# the "turbulence." keywords are turbulence parameters, that are
# explained in the "multifractal" documentation. 

s.transformEnd()

# Model water with a physical material.
water = s.newMaterial( "physical",
    [ "fresnel", 1, 0.3, 0.0,
      "IOR", 1.33,
      "kr", vector3( 1, 1, 1 ),
      "kt", vector3( 1, 1, 1 ),
      "kd", 0.0,
      "km", 0.03,
      "shinyness", 0.5,
      "displacement", waterbumps ] )

# the choosed type is "physical", because this provides physical
# parameters, very good to model liquids, glasses and metals. 
# note the use of the waterbumps pattern as a displacement.


# Model the ocean fundals in a similar way.
earthbumps = s.newPattern( "multifractal",
    [ "basis", "sin",
      "scale", 10.0,
      "depth", 0.5,
      "turbulence.distortion", 1.0,
      "turbulence.omega", 0.1, 0.3,
      "turbulence.lambda", 2.0,
      "turbulence.octaves", 5 ] )

earth = s.newMaterial( "diffuse",
    [ "kr", vector3( 0.8, 0.75, 0.7 ),
      "displacement", earthbumps ] )


# Here starts the sky.
# It contains a lot of volumetric clouds, especially at the horizon,
# so it is a bit complex. 

# Volumetric clouds are modeled with an interior and a pattern that modulates its density.
s.transformBegin( transform().scaling( vector3( 100, 100, 100 ) ) )
s.transformBegin( transform().translation( vector3( 0, 0, -0.5 ) ) )

cloudpattern = s.newPattern( "multifractal",
    [ "value",
           0.0, 1.0, 1.0,
           0.3, 0.1, 0.1,
      "scale", 1.0,
      "turbulence.distortion", 1.0,
      "turbulence.omega", 0.5, 0.8,
      "turbulence.lambda", 2.0,
      "turbulence.octaves", 3 ] )

# Make the output distribution go from 1 to 0.1 to model clouds.

s.transformEnd()
s.transformEnd()

cloudinterior = s.newInterior( "cloud",
    [ "kr", vector3( 2.0, 0.8, 0.4 ),
      "kaf", vector3( 0.6 * 0.035, 0.8 * 0.035, 0.4 * 0.035 ),
      "density", 1.0,
      "density", cloudpattern,
      "sampling", 0.07,
      "shadow-caching", vector3( -1000, -1000, -1 ), vector3( 1000, 1000, 100 ),
      "density-caching", 2048, vector3( -1000, -1000, -1 ), vector3( 1000, 1000, 100 ) ] )

# Note that our scene will have a radius of 1000 unities, and our
# camera would be at its center, so with a sampling factor of 0.07 we
# allow 70 samples per ray: an enormous quantity! This will make our
# scene render slowly, but the caches will give a help. Obviously if
# you remove these volumetric clouds the rendering will be much faster.
# Here we don't care about speed however, since we want only to
# produce a single, astonishing image...


# Now model the fundal, a blue sky made of flat clouds that will be
# wrapped on a sphere.

skypattern1 = s.newPattern( "linear-v",
    [ "color",
          0.2, vector3( 0.8, 0.9, 1.0 ), vector3( 0.8, 0.9, 1.0 ),
	  1.0, vector3( 0.2, 0.4, 0.9 ), vector3( 0.2, 0.4, 0.9 ) ] )

s.transformBegin( transform().scaling( vector3( 80, 80, 10 ) ) )

skypattern2 = s.newPattern( "multifractal",
    [ "color",
          0.2, vector3( 0.2, 0.4, 0.9 ), vector3( 0.2, 0.4, 0.9 ),
	  1.0, vector3( 0.2, 0.3, 0.7 ), vector3( 0.2, 0.3, 0.7 ),
      "scale", 1.1,
      "turbulence.distortion", 1.0,
      "turbulence.omega", 0.5, 0.8 ] )

s.transformEnd()

skypattern = s.newPattern( "blend",
    [ "pattern", skypattern1,
      "gradient",
          0.3, skypattern1, skypattern1,
          1.0, skypattern2, skypattern2 ] )

# Note that we actually created two patterns, and we merged them
# together with a "blend".
# The first pattern is a linear gradient that will span the V
# direction of the parametric surface we will attach it to.
# In this case we will use it on a sphere, where the V direction is
# the one which connects the north and south poles (that is to say a
# line of constant U and varying V is a meridian).
# This gradient associates a color to each parallel of the sphere,
# going from bright blue near the horizon to dark blue near the
# azimuth.
# The second pattern is again a "multifractal", which we use to model
# very distant clouds. Note that we stretch it with a scaling, so that 
# the clouds will look wide and thin.
# The "blend" pattern finally blends the two. It uses the pattern
# specified with "pattern" to mix more patterns. In particular it
# defines a pattern-gradient that smoothly interpolates between
# different patterns. In this case we use the linear pattern both to
# model the distribution of the gradient and to model the gradient
# itself.
# The numeric value of the linear pattern has not been specified
# (with a value-gradient), and so it goes from 0 to 1, as default.
# Thus the "blend" will make a transition that goes from a clear
# and bright sky near the horizon (at the V value of 0.3) to a cloudy
# sky near the azimuth (at the V value of 1.0).


# Create the sky material.
s.interiorBegin( cloudinterior )

sky = s.newMaterial( "matte", 
    [ "kc", vector3( 1, 1, 1 ),
      "kc", skypattern,
      "shadowing", 0.0 ] )

s.interiorEnd()

# "matte" is a material made to create matte objects, that are not
# shaded by light, but that emit a uniform color. In this case this
# color is first set to white (1, 1, 1) and then scaled by the skypattern.
# The result will be the skypattern itself.


# Create a water disc.
s.materialBegin( water )

s.addObject( s.newObject( "disc", [ "radius", 1000.0 ] ) )

s.materialEnd()


# Create an under-water disc made of earth.
s.transformBegin( transform().translation( vector3( 0, 0, -10 ) ) )

s.materialBegin( earth )

s.addObject( s.newObject( "disc", [ "radius", 1000.0 ] ) )

s.materialEnd()

s.transformEnd()


# Create the sky sphere.
s.transformBegin( transform().scaling( vector3( 1, 1, 0.1 ) ) )

s.materialBegin( sky )

s.addObject( s.newObject( "sphere", [ "radius", 1000.0 ] ) )

s.materialEnd()

s.transformEnd()


# Put a halo imager to create glowing effects on the camera lens
halo  = s.newImager( "halo", [ "kr", 0.08, "km", 0.013 ] )
saver = s.newImager( "tga-saver",
		     [ "file", "ocean.tga",
		       "imager", halo ] )

s.imagerBegin( saver )

camera = s.newCamera( "pinhole",
    [ "eye", vector3( 0, -8, 4 ),
      "aim", vector3( 0, 0, 4 ),
      "aa-samples", 2, 5 ] )

s.imagerEnd()

s.render( camera, 400, 300 )
