//From: Marc Champagne
//Subject: Mika Diamond
//Date: 24 Mar 2003 19:41:42 EST
// FILE : diamond.pov
// SCENE: A diamond in its best(?) display of colors
// DATE : Sept 2002
// EMAIL: marcch.AT.videotron.DOT.ca
// Copyright 2002, Marc Champagne, Please ask!

// Notes added by Don Barron who scratched around the websites and located the geometry
// which Marc Champagne probably used.
// (1) Don Barron ( a long-time POVRAY addict for its value in scientific optics
// modelling ) became interested in the diamond cuts because Mrs.Barron
// inherited an antique ring of 6 large round brilliants set in platinum - but they didn't really
// sparkle. So,a thorough clean and lo...the beauty is restored. But after
// a few weeks of continuous wearing....the sparkle and color fades. Hmmm... the
// likely cause is grease on the rear facets of the pavillion spoiling
// the 'total internal reflection' nominally occurring thereat. Diamond has a very
// strong affinity for grease - a greased plate is frequently used to sift very
// small diamonds in water. Question - is it possible to apply a dielectric coating
// to the critical facets which will prevent this degradation? To be investigated....
// (2) But back at POVRAY, it is essential to have the correct value of 'Dispersion'.
// The value is 1.0 + the difference in IOR over the range of wavelengths
// rather cleverly but obscurely implemented in POV. No-one on the TAG
// seems willing to disclose how this is achieved - but it's pretty convincing!
// (3) When looking directly at the diamond the chromatic effects seem not to appear
// until a very large number of 'photons' and wavelengths are used. 9e4 Photons is insufficient
// and creates a bright area of 'polka dots' under the pavillion. 3e5 is barely adequate - the useful
// minimum is 1e6. Even 32 dispersion samples may not be enough. My home PC is a 1GB RAM/1800+ Athlon
// and it needs several hours cpu time to create credible results in a 640*480 aa0.3 rendering with
// these values. These brought my PC to its knees - there's probably a memory leak. I'm tempted to
// upgrade my PC to 4Gb - but it hardly seems worth the risk for this one exercise.
// (4) It's much easier to catch the fire by viewing a screen from the girdle against the light.
// The chromatic retroreflections become very obvious with only 1e4 photons and the compute time
// for the fire is very much lighter. 1e5 photons cuts down on the polka dots. 1e6 is better but
// if there's anything of the diamond in the view then....
// (5) I've used a spotlight and put a white diffuse screen behind and under the diamond
// to catch the chromatic fire.
// (6) I suppose there must be a lighting angle/viewing angle combination which gives
// the maximum beauty - but what is that alignment?
// (7) The normal incidence reflectivity R0 of diamond is 17%. The fit to the
// fresnel reflectivity/angle function is probably "R(T) = R0 +(1-R0)*pow(1-cos(T),5)"
// (8) I've messed about with the names of the variables - I find it much easier to
// follow code when the lines are tidy.
// (9) Make a 1e4 photons/16 dispnsamps movie with 256 frames at 640 x 480 to get the benefit
// of the fire. Making an mpeg version seems to lose much of the fire.
// (10) The Display_Gamma in pov.ini and DispGamma here are useful to manipulate the polka dots
// with low numbers of photons.

#include "colors.inc"

/******************SCENE OPTIONS*****************/

#declare TestMatrl = no; // Test of the diamond material using a sphere
#declare VueDiamnd = yes; // Geometry setup to view the diamond(s)
#declare ViewFire = no; // Geometry setup to view the fire
#declare TheFulWrx = yes; // The full works of photon mapping
#declare SavFoMaps = no; // Save the photon maps for a rerun of the viewpoint
#declare ReUseMaps = no; // Re-use the photon maps
#declare SkyOvrHed = no; // A semi-cloudy sky overhead

#if(VueDiamnd)
#declare FotnCount = 1e5; // Step this up from 1e4 to 3e6.....and go to bed
#declare PutLyteAt = < 5.00, 30.00, -10.00 >; // Nominal lightsource position
#declare PntLyteAt = < 0.20, 0.25, 0.00 >; // Spotlight pointed here
#declare PutCamrAt = < -1, 2, -4 >; // Camera located here
#declare LookAt = <-0.00, 0.00+0.2, 0.00 >; // Camera looks here
#declare CamrAngle = 50*0.4; // Camera angle of view
#declare AreaLight = no; // Area lights?
#declare NAreaLytz = 5; // Number of arealights parameter
#declare SpotLight = yes; // Spotlight?
#declare SpotAngle = 3.5; // Angle of spotlight
#declare CyldrScrn = no; // Place a cylindrical screen to show the fire
#declare Solitaire = yes; // A single diamond - else a triplet
#declare LyteBryte = 1.5; // Brightness of lightsource
#declare NDspSamps = 32; // Number of wavelengths in lightsource
#end

#if(ViewFire)
#declare FotnCount = 1e4;
#declare AreaLight = no;
#declare SpotLight = yes;
#declare PutLyteAt = < 1.00, 1.00 + LocalKlok*20,-10.00 >;
#declare SpotAngle = 10;
#declare PntLyteAt = < 0.00, 0.25, 0.00 >;
#declare PutCamrAt = < 0.0, 1.4, 1.0 >;
#declare CamrAngle = 60;
#declare LookAt = <-0.00, 0.25, -10>;
#declare CyldrScrn = no;
#declare Solitaire = yes;
#declare LyteBryte = 3.0;
#declare NDspSamps= 32;
#end

#if(TheFulWrx)
#declare NuAlynmnt = yes;
#declare Transprnt = yes;
#declare PhotnMaps = yes;
#declare RfIndices = yes;
#declare Disprshns = yes;
#declare Reflexons = yes;
#else
#declare Transprnt = no; #declare FlterAmount = 0.00;
#declare PhotnMaps = no; #declare PhotonCount = 1.00;
#declare Disprshns = no; #declare Dispersion = 1.00; #declare NDispSamps = 2;
#declare DymndColr = 1.0; #declare Reflexons = no;
#declare RfIndices = no;
#end

#if(Transprnt)
#declare FltAmount = 0.98;
#declare DymndColr = 0.98;
#declare Reflexons = yes;
#else
#declare FltAmount = 0.00;
#declare DymndColr = 0.5;
#declare Reflexons = no;
#end

#declare FullScene = yes;
#declare DebugAxis = no;
#declare DbugColrs = no;
#declare CrossSexn = no;
#declare DebugCuts = no;
#declare TraceDeep = 60;
#declare AngOffset = 20.0;
#declare DispGamma = 1.0;
#declare LocalKlok = clock;
#declare Anamorph = 1.0; // Aspect of the PC monitor, relative to 4/3

global_settings { max_trace_level TraceDeep assumed_gamma DispGamma
#if ( PhotnMaps ) photons { count FotnCount
#if(SavFoMaps) save_file "diamond.ph" #end
#if(ReUseMaps) load_file "diamond.ph" #end
}
#end
}

/********TOWLOSKI's DIAMOND GEOMETRY - THE 'BRILLIANT'***********/

#declare Diameter = 1;
#declare Radius = Diameter /2;
#declare CrownHeight = Diameter * ( 16.2 / 100 );
#declare GirdleDepth = Diameter * ( 01.0 / 100 );
#declare PavyonDepth = Diameter * ( 43.1 / 100 );
#declare OverallDepth = CrownHeight + GirdleDepth + PavyonDepth;
#declare TableWidth = Diameter * ( 53.0 / 100 );
#declare TableRadius = TableWidth/2;
#declare CrownBazlAng = 34.50;
#declare CrownStarAng = 20.00; // Ideal = 15.00, unable to find exact specs for placing these facets
#declare CrnUpprGrdlAng = 39.22; // Ideal = 42.00, unable to find exact specs for placing these facets
#declare GrdlAng = 90.00;
#declare PavLowaGrdlAng = 42.75;
#declare PavlAng = 40.75;

/***************DIAMOND CONSTRUCTION*************/

#if ( DebugCuts )
#declare Cut = union { sphere { 0, 0.02 } sphere { -y*.02, .01 } pigment { rgb <1,0,0> } no_shadow }
#declare Stone = union {
#else
#declare Cut = object { plane { y, 0.00 } }
#declare Stone = intersection {
#end


/****************THE TABLE**************************/

object { Cut translate y * OverallDepth
#if ( DbugColrs ) pigment {rgb <0,1,1> } #end
}

/*************THE CROWN - STAR FACET*****************/

#declare Faces = 8;
#declare Turn = 0;
#while ( Turn < Faces )
object { Cut rotate -z*CrownStarAng
translate x*TableRadius
translate y*( OverallDepth - .0075 ) // Unable to find exact data for these facets
rotate y*360/Faces/2
rotate y*360/Faces*Turn
#if ( DbugColrs ) pigment { rgb <0,1,0> } #end
}
#declare Turn=Turn+1;
#end


/*************THE CROWN - BAZEL FACET****************/

#declare Faces = 8;
#declare Turn = 0;
#while ( Turn < Faces )
object { Cut
rotate -z*CrownBazlAng
translate x*Radius
translate y*( PavyonDepth + GirdleDepth )
rotate y*360 / Faces * Turn
#if ( DbugColrs ) pigment { rgb <1,0,0> } #end
}
#declare Turn=Turn+1;
#end


/*********THE CROWN - UPPER GIRDLE FACET*************/

#declare Faces = 16;
#declare Turn = 0 ;
#while ( Turn < Faces )
object { Cut rotate -z*CrnUpprGrdlAng
translate x*( Radius -.01 )
translate y*( PavyonDepth + GirdleDepth )
rotate y*360/Faces/2
rotate y*360/Faces*Turn
#if ( DbugColrs ) pigment {rgb <1,0,1> } #end
}
#declare Turn=Turn+1;
#end

/*******************THE GIRDLE***********************/

#declare Faces=32;
#declare Turn=0;
#while (Turn<Faces)
object { Cut rotate -z*GrdlAng
translate x*( Radius - .01 )
rotate y*360 / Faces * Turn
#if ( DbugColrs ) pigment { rgb <1,1,0> } #end
translate y * PavyonDepth // not needed, only used for visual when Debug is ON
}
#declare Turn=Turn+1;
#end

/********THE PAVYON - LOWER GIRDLE FACET*************/

#declare Faces = 16;
#declare Turn = 0;
#while ( Turn < Faces )
object { Cut rotate -z*((90-PavLowaGrdlAng ) + 90 )
rotate y*360/Faces*Turn
rotate y*360/Faces/2
#if ( DbugColrs ) pigment {rgb <0,1,0.5> } #end
translate -y * .0225
}
#declare Turn=Turn+1;
#end


/*****************THE PAVYON FACET*******************/

#declare Faces = 8;
#declare Turn = 0;
#while ( Turn < Faces )
object { Cut rotate z*( ( 90-PavlAng ) + 90 )
rotate y*360/Faces*Turn
#if ( DbugColrs ) pigment {rgb <1,1,1> } #end
}

#declare Turn=Turn+1;
#end

/********************THE CULET***********************/

object { Cut rotate z*180 translate y*0.02 }

/**********************DEBUG*********************/

#if ( CrossSexn )
object { Cut rotate -x*90 pigment { rgb <1,1,1> } }
#end
bounded_by { box { <-Radius-0.1,OverallDepth+0.1,-Radius-0.1 >,< Radius+0.1,-0.1,Radius+0.1 > } }
}

/******MATERIAL PROPERTIES OF DIAMOND************/

#declare RefracIndx = 2.417;
#declare Dispersion = 1.044+.04;
#declare DymndMat = material { texture { pigment { rgb DymndColr filter FltAmount }
finish { #if(PhotnMaps)
ambient 0.0 diffuse 0.03 specular 0.00 roughness 0.01
#if ( Reflexons ) reflection { 0.17,1.0 fresnel } #end
#else
ambient 0.0 diffuse 0.40 specular 0.20 roughness 0.100 phong 1 phong_size 300
#if ( Reflexons ) reflection { 0.2, 0.1 fresnel metallic } #end
#end
}
}
interior { #if ( RfIndices ) ior RefracIndx #end
#if ( PhotnMaps & Disprshns ) dispersion Dispersion dispersion_samples NDspSamps #end
}
}


/*******************THE DIAMOND *****************/

#declare MyGem = object { Stone material { DymndMat } }
#if(Solitaire)
#declare MyCarats = object { MyGem rotate -x*PavlAng }
#else
#declare MyCarats = union { object { MyGem rotate -x*PavlAng }
object { MyGem rotate z*PavlAng translate -x * 1.0 }
object { MyGem rotate x*PavlAng translate x * 1.2 }
}
#end

/*************SHOW THE DIAMOND SCENE*************/

#if ( FullScene )
light_source { PutLyteAt, rgb LyteBryte
#if(SpotLight = no)
parallel
#else
spotlight radius SpotAngle falloff 1.8*SpotAngle tightness 1 point_at PntLyteAt
#end
#if ( AreaLight ) area_light x*4*3, y*4*3, NAreaLytes, NAreaLytes adaptive 1 jitter #end
#if ( PhotnMaps ) photons { refraction on reflection on } #end
}
union { #if(VueDiamnd) plane { y,0 pigment { rgb<0.3,0.4,0.5> } finish { ambient 0.0 diffuse 0.8 reflection 0} } #end
#if(ViewFire)
plane { z,-12 pigment { rgb 1 } finish { ambient 0.0 diffuse 1.0 } }
#if(CyldrScrn)
intersection { cylinder { -y*1.0,y*2.0,3}
cylinder { -y*1.1,y*2.1,1.2 inverse }
plane { z, 0.4 }
plane { y,3}
scale <1.5,1,1>
}
#end
#end
#if(PhotnMaps ) photons { target 0.5 refraction off reflection off} #end
}
#else
light_source { < 25,50, 100> rgb 1 }
#end

#if(TestMatrl = no)
object { MyCarats rotate y*(5*LocalKlok + AngOffset)
#if ( PhotnMaps ) photons { target refraction on reflection on } #end
}
#else sphere { 0,0.35 translate y*0.35 material { DymndMat} }
#end

#if(SkyOvrHed)
#declare Cldynss = 0.25; #declare SkyScale = 1;#declare Bryte = 0.5;
#declare SkyCol1 = rgb<0.20,0.60,0.80>*Bryte;
#declare SkyCol2 = rgb<0.80,0.80,0.80>*Bryte;
#declare SkyCol3 = rgb Bryte;
#declare SkyCol = color_map { [ 0.0 color SkyCol1 ]
[ 0.1 color SkyCol1 ]
[ 0.7 color SkyCol2 ]
[ 1.0 color SkyCol3 ]
}

sky_sphere { pigment { bozo turbulence 1.2*(1+Cldynss) lambda 2*(1+Cldynss)
color_map { SkyCol }
scale 2 translate -1
scale <SkyScale, 0.5*SkyScale,SkyScale>
rotate y*90
}
}

#end

camera { location PutCamrAt look_at LookAt angle CamrAngle up y*1 right x*1.33*Anamorph}

/************************************************/



/****************DEBUG GRATICULE ****************/

#declare Size = .002;
#if ( DebugAxis )
union { cylinder { < -30, 0, 0 >, < 30.0, 0, 0 >, Size pigment { Red }}
cylinder { < 0, -30, 0 >, < 0.0, 30, 0 >, Size pigment { Green }}
cylinder { < 0, 0, -30 >, < 0.0, 0, 30 >, Size pigment { Blue }}
cylinder { < 0.500, -30, 0 >, < 0.5, 30, 0 >, Size pigment { Green }}
cylinder { < 0.500, -30, 0 >, < -0.5, 30, 0 >, Size pigment { Green }}
cylinder { <-0.265, -30, 0 >, < -0.265, 30, 0 >, Size pigment { Green }}
cylinder { < 0.265, -30, 0 >, < 0.265, 30, 0 >, Size pigment { Green }}
cylinder { < -30, OverallDepth, 0 >, < 30, OverallDepth, 0 >, Size pigment { Red }}
cylinder { < -30, PavyonDepth, 0 >, < 30, PavyonDepth, 0 >, Size pigment { Red }}
cylinder { < -30, PavyonDepth+GirdleDepth, 0>, < 30, PavyonDepth+GirdleDepth, 0 >, Size pigment { Red }}
no_shadow
}
#end


//(MIKA) Marc Champagne
//marcch.AT.videotron.DOT.ca
//Montreal, CANADA