POV-Ray : Newsgroups : povray.binaries.images : Multi-level Truchet tiles : Re: Multi-level Truchet tiles Server Time
5 Nov 2024 14:22:21 EST (-0500)
  Re: Multi-level Truchet tiles  
From: Samuel B 
Date: 28 Sep 2023 17:55:00
Message: <web.6515f5769c496f2116bed5696e741498@news.povray.org>
"Chris R" <car### [at] comcastnet> wrote:
> "Samuel B." <stb### [at] hotmailcom> wrote:
> > Hi,
> >
> > It's like regular Truchet tiles, but the cells are subdivided, and subsets of
> > tiles are selected for each level of scale [...]
>
> Very cool!  I'd be interested in seeing the code at some point.
>
> (Starts going down rabbit hole on Truchet tiles...)
>
> -- Chris R.

Hi Chris, thank you.

Truchet tiles are pretty versatile (:J) and simple at their most basic level.
But the multi-level stuff can complicate things a bit.

If you've got a compatible device (recent-ish PC or smart phone) you can search
Truchet tiles on Shadertoy.com to see what things other people have done. Crazy
stuff.

Anyway, here's the entire code, sans glare:

/*

 Multi-level-Truchet.pov

 2023 Sam Benge

 More tile types are possible but not yet implemented; the TilesSm, TilesMd and
 TilesLg arrays can be expanded as needed.

 Command line options:
  +fn +f +a0.03 +am2 +r3

*/

#version 3.7;

global_settings{assumed_gamma 1.0}


/*--   Settings   --*/

#declare RenderSingleArea = false;
#declare RandomThreshold = 0.33; // (0.0-1.0)
#declare RandomSeed    = 1003;
#declare TorusThickness  = 0.2;
#declare GlobalTranslate = <-6.7, 0, -14.5>;

#declare UseFocalBlur   = true;
#declare FocalBlurSamples = 10;

#declare SunDir = <1, .7, .5>;
#declare RGBSun = srgb 1.5*<2, 1.95, 1.9>;
#declare RGBSky = srgb .5;

#declare CamPos = .75 * <4, 15, -20>;

/*-- End Settings --*/


#default{ finish{ambient 0} }

#include "transforms.inc"

camera{
 fisheye
 right x*.7 up y*.7/1.77
 location CamPos
 look_at 0
 angle 120
 #if(UseFocalBlur)
  aperture 1 focal_point 0 blur_samples FocalBlurSamples variance 0
 #end
}

// sky
#if(1)
 sky_sphere{
  pigment{
   spherical
   scale 2
   translate y
   poly_wave 4
   Point_At_Trans(SunDir)
   color_map{
    [0 RGBSky]
    [1 RGBSun]
   }
  }
 }
#end

// torus macros
#macro TorusQuarter(R1, R2)
 #local Eps = 0.001;
 torus{
  R1, R2
  clipped_by{box{<0, -R2-Eps, 0>, R2+Eps+<R1, 0, R1>}}
 }
#end

#macro TorusHalf(R1, R2)
 #local Eps = 0.001;
 torus{
  R1, R2
  clipped_by{plane{-z, 0}}
 }
#end

// some torus quarter and torus half objects
#declare TQ1 = object{TorusQuarter(1, TorusThickness)}
#declare TQ3 = object{TorusQuarter(3, TorusThickness)}
#declare TH1 = object{TorusHalf(1, TorusThickness)}

// small tiles
#declare TilesSm =
 array[2]{
  union{
   object{TQ1 translate <-1, 0, -1>}
   object{TQ1 rotate y*180 translate <1, 0, 1>}
  },
  union{
   cylinder{-x, x, TorusThickness open}
   cylinder{-z, z, TorusThickness open}
  }
 }

// medium tiles
#declare TilesMd =
 array[3]{
  union{
   object{TQ1 translate <-2, 0, -2>}
   object{TQ1 rotate y*90 translate <-2, 0, 2>}
   object{TQ1 rotate y*180 translate <2, 0, 2>}
   object{TQ1 rotate y*270 translate <2, 0, -2>}
  },
  union{
   object{TH1 translate <0, 0, -2>}
   object{TH1 translate <0, 0, -2> rotate y*90}
   object{TH1 translate <0, 0, -2> rotate y*180}
   object{TH1 translate <0, 0, -2> rotate y*270}
  },
  union{
   object{TQ1 translate <-2, 0, -2>}
   object{TQ3 translate <-2, 0, -2> rotate y*180}
   cylinder{-2*x, 2*x, TorusThickness open translate z}
   cylinder{-2*z, 2*z, TorusThickness open translate x}
  }
 }

// large tiles
#declare TilesLg =
 array[4]{
  union{
   object{TQ1 translate <-4, 0, -4>}
   object{TQ1 rotate y*90 translate <-4, 0, 4>}
   object{TQ1 rotate y*180 translate <4, 0, 4>}
   object{TQ1 rotate y*270 translate <4, 0, -4>}

   object{TH1 translate <0, 0, -4>}
   object{TH1 translate <0, 0, -4> rotate y*90}
   object{TH1 translate <0, 0, -4> rotate y*180}
   object{TH1 translate <0, 0, -4> rotate y*270}
  },
  union{
   object{TH1 translate <-2, 0, -4>}
   object{TH1 translate <2, 0, -4>}
   object{TH1 translate <-2, 0, -4> rotate y*90}
   object{TH1 translate <2, 0, -4> rotate y*90}
   object{TH1 translate <-2, 0, -4> rotate y*180}
   object{TH1 translate <2, 0, -4> rotate y*180}
   object{TH1 translate <-2, 0, -4> rotate y*270}
   object{TH1 translate <2, 0, -4> rotate y*270}
  },
  union{
   object{TQ1 translate <-4, 0, -4>}
   object{TQ3 translate <-4, 0, -4>}
   object{TQ1 translate <-4, 0, -4> rotate y*90}
   object{TQ3 translate <-4, 0, -4> rotate y*90}
   object{TQ1 translate <-4, 0, -4> rotate y*180}
   object{TQ3 translate <-4, 0, -4> rotate y*180}
   object{TQ1 translate <-4, 0, -4> rotate y*270}
   object{TQ3 translate <-4, 0, -4> rotate y*270}
  },
  union{
   object{TQ1 translate <-4, 0, -4>}
   object{TQ3 translate <-4, 0, -4>}
   object{TQ1 translate <-4, 0, -4> rotate y*180}
   object{TQ3 translate <-4, 0, -4> rotate y*180}
   object{TH1 translate <-2, 0, -4> rotate y*90}
   object{TH1 translate <2, 0, -4> rotate y*180}
   object{TH1 translate <-2, 0, -4> rotate y*270}
   object{TH1 translate <2, 0, -4>}
  }
 }

// place variously-sized tiles into main array
#declare Tiles = array[3]{TilesLg, TilesMd, TilesSm}

// basic ground tile color
#declare GroundCol = <.55, .5, .65>;

// teture macro for ground tiles
#macro Texture(Col)
 texture{
  pigment{rgb Col}
  normal{granite .1 scale .001}
  finish{reflection{.5, 1 falloff 2 metallic 1} }//diffuse 0}
 }
#end

// ground tile macro
#macro Tile(Size)
 height_field{
  function Size*16, Size*16 {
   pigment{
    boxed
    scale 1/2
    translate (x+y)/2
    color_map{
     [0 rgb 0]
     [.2/Size rgb 1]
    }
   }
  }
  smooth
  translate -(x+z)/2
  scale <2*Size, .1, 2*Size>
  translate - y*.1
 }
#end

// Ground tiles. They must be declared before being placed into arrays because
of the texture macro.
#declare GT1 =
 object{
  Tile(4)
  Texture(.75 * GroundCol)
 }

#declare GT2 =
 object{
  Tile(2)
  Texture(.50 * GroundCol)
 }

#declare GT3 =
 object{
  Tile(1)
  Texture(.25 * GroundCol)
 }

// place ground tiles into array
#declare GroundTiles = array[3]{GT1, GT2, GT3}

// random integer
#macro rint(A) floor(A*rand(Seed)) #end

// the Truchet tile-subdivision macro
#macro Iterate(I, S, Pos)

 // four diagonal directions
 #local Dir = array[4] {<-1, 0, -1>, <1, 0, -1>, <-1, 0, 1>, <1, 0, 1>}

 // if iteration value more than equals zero
 #if(I>=0)

  // test against threshold and iteration value
  #if(rand(Seed)<RandomThreshold & I>0 | I=3)

   // place new Iterate macros

   #for(A, 0, 3)
    Iterate(I-1, S/2,  Pos+S*Dir[A])
   #end

  #else

   // place the objects

   #local ID = max(0, 2-I);

   // Truchet tile
   object{
    Tiles[ID][rint(dimension_size(Tiles[ID], 1))]
    rotate y*90*rint(2)
    translate Pos
   }

   // ground tile
   object{
    GroundTiles[ID]
    translate Pos-y*TorusThickness
   }

  #end

 #end

#end

// a random seed
#declare Seed = seed(RandomSeed);

// render objects
union{

 // render just one subdivided tile
 #if(RenderSingleArea)

   Iterate(3, 4, <0, 0, 0>)
   translate -GlobalTranslate

 // render a bunch of subdivided tiles along the x and z axes
 #else

  // a point of interest
  sphere{y*2, 2 translate <4, -.19, 12>}

  // loop over x & z axes and place tiles
  #for(Z, -2, 7)
   #for(X, -7, 7)
    union{
     Iterate(3, 4, <0, 0, 0>)
     translate 16*<X, 0, Z>
    }
   #end
  #end

 #end

 // a golden texture
 texture{
  pigment{rgb <.6, .4, .2>}
  normal{granite .1 scale .001}
  finish{reflection{ 1 metallic 1}}
 }

 // translate object
 translate GlobalTranslate
}


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.