POV-Ray Object Collection
Curved Paving Macro


Overview
Examples
Macros
Variables

Two sections of pavers cut to fit a path (see Example 7 below)

Overview


Three adjoining sections of pavers (see Example 1 below)
These macros enable you to add Curved Paving in the "bogen" (or "segmental arc") pattern to your POV-Ray scenes by invoking the curvedpaving macro which is provided in the include file 'curvedpaving.inc'. This generates a POV-Ray CSG object that will readily tesselate (seamlessly interlock with adjacent sets of blocks).

The sample scene file 'curvedpaving.pov' contains plenty of examples showing the use of the various options and settings available with these macros. These examples are described and illustrated below.

The default settings produce a 0.1 unit thick layer of paving stones about 1.4 POV-Ray unit wide, but it's easy to override the defaults with the settings described (see Variables below).

The top surface of the generated object is aligned with the XZ plane (at a height of y=0). The object is centred on the Z axis and heads away from the origin in the +Z direction. From here the generated object can be translated (or rotated) in the normal way. The macros set certain values that can be extremely useful when positioning/aligning sets of blocks, as demonstrated in a number of the examples below.

The "bogen" style of paving became popular in many European cities with the advent of horse-drawn wagons as the regular interlocking structure proved extremely resilient and efficient at distributing heavy loads down into the bedding material. They are however complex and expensive to lay as blocks at the outer reaches of the arc need to be smaller than those at the centre.

Return to Table of Contents


Examples

The curvedpaving.pov scene file contains a series of examples demonstrating the use of the 'CurvedPaving' macro. You can render any of these examples simply by setting the 'Example' variable at the top of the scene file. These examples are explained and illustrated here:
Example=0; Default settings
Example 0 renders the default slab of paving blocks.

The default settings produce a layer of paving stones about 1.4 POV-Ray unit wide and 0.08 units thick laying under the XZ plane so that the top surface is at a height of y=0. The slab is centred on the Z axis and heads away from the origin in the +Z direction with the top surface of the centre of the first row of blocks starting at <0,0,1>.

 camera {orthographic
   location <0,2.8,1.74>
   look_at 1.75*z>
 }
 light_source {<-10,20,-5>, rgb 1}
 #include "curvedpaving.inc"
 CurvedPaving("")

You can also wrap the macro call in an object statement and perform translations, rotations and scaling on the result. For example:

 object {CurvedPaving("")
   scale 0.5
   rotate <3,0,4>
   translate x*1.3
 }

Example=1; Aligning Sections
Example 1 renders three copies of the default slab (extended to include 60 rows of blocks) side by side.
  #declare CurvedPaving_Rows = 60;
  #declare Section = CurvedPaving("")
  object {Section}
  object {Section translate CurvedPaving_CentreToCentre*x}
  object {Section translate -CurvedPaving_CentreToCentre*x}

This example illustrates how the variable 'CurvedPaving_CentreToCentre' (which is set by the 'CurvedPaving' macro) can be used to translate blocks to the left or right. The sections are designed to fit together when translated in this way. You can also add separate runs of block together end to end by simply translating in Z by the product of the depth of the block and the number of rows of blocks (CurvedPaving_BlockDepth * CurvedPaving_Rows).

If you don't set a control variable the 'CurvedPaving' macro sets a default value that you can subsequently access in your scene. This example illustrates this by using the 'CurvedPaving_BlockThickness' variable to align the top of the foundations with the bottom of the blocks and to make sure that the plane used to define the grass is below the foundations.

If you change settings between calls to the 'CurvedPaving' macro and you want to use values that are calculated by the macro, then you should keep a copy of those values as illustrated in example 6. That example joins together 3 panels generated using different radii.

Example=2; Color Settings
Example 2 renders three sections of blockwork with different color settings (having set the contrast to '0').

   #declare CurvedPaving_Contrast = 0;
   #declare CurvedPaving_Radius = 0.5;
   #declare CurvedPaving_MinColor = <0,0,0>;
   #declare CurvedPaving_MaxColor = <1,1,1>;
   object {CurvedPaving("")}
 
   #declare CurvedPaving_MinColor = <0.4,0.4,0.4>;
   #declare CurvedPaving_MaxColor = <0.8,0.8,0.8>;
   object {CurvedPaving("") translate -CurvedPaving_CentreToCentre*x}
 
   #declare CurvedPaving_MinColor = <1.0,0.7,0.6>;
   #declare CurvedPaving_MaxColor = <1.0,0.9,0.7>;
   object {CurvedPaving("") translate CurvedPaving_CentreToCentre*x}

The central block shows the full color range with the minimum color (CurvedPaving_MinColor) specified as <0,0,0> (Black) and the maximum color (CurvedPaving_MaxColor) as <1,1,1> (White). Because the Red, Blue and Green color components are randomised separately and can each vary between 0 and 1 you can get blocks of any color.

The block on the left shows a reduced colour range with the minimum set to <0.4,0.4,0.4> and the maximum to <0.8,0.8,0.8>. This clips off the brighter and darker extremes, but still allows a significant color variation.

The block on the right adds a buff (yellow/red) biase with the minimum set to <1.0,0.7,0.6> and the maximum to <1.0,0.9,0.7>. With these settings you always get a full red channel, the green component can vary from 0.7 to 0.9 and the blue component from 0.6 to 0.7. The result is a yellow/buff color with a limited degree of variation.

Example=3; Contrast Settings
Example 3 renders three sections of blockwork with different contrast settings using the default maximum and minimum color settings (CurvedPaving_MinColor=<0.6,0.3,0.3>; CurvedPaving_MaxColor=<0.75,0.35,0.35>;).

   #declare CurvedPaving_Radius = 0.5;
   #declare CurvedPaving_Contrast = 0;
   object {CurvedPaving("")}
  
   #declare CurvedPaving_Contrast = 1;
   object {CurvedPaving("") translate -CurvedPaving_CentreToCentre*x}
  
   #declare CurvedPaving_Contrast = 0.5;
   object {CurvedPaving("") translate CurvedPaving_CentreToCentre*x}

The central block shows the base color without contrast (CurvedPaving_Contrast=0).

The left hand block shows a contrast setting of '1'. This permits the colors to be darkened from their base colors all the way down to Black.

The right hand block uses a contrast setting of '0.5', permitting the colors to be darkened half way to black (the default setting).

Example=4; Finish and Normals
Example 4 illustrates the use of the finish and normal settings.

   object {CurvedPaving("")}
  
   #declare CurvedPaving_Normal = normal {agate scale <0.001,0.01,0.001>}
   object {CurvedPaving("") translate -CurvedPaving_CentreToCentre*x}
  
   #declare CurvedPaving_Normal = normal {granite scale 0.1}
   #declare CurvedPaving_Finish = finish {phong 1}
   object {CurvedPaving("") translate CurvedPaving_CentreToCentre*x}

The central block uses the default settings which apply a granite normal scaled by 0.1 and no finish (actually a setting of phong 0).

The left hand block uses a normal of agate scaled by <0.001,0.01,0.001> to give a fine grainy normal in the X and Z dimensions, with a more pronounced normal in the Y dimension to emphasize the effect (a deeply pitted surface).

The right hand block uses the granite normal with a phong of 1 to make the surface glisten as it might when wet. You could also add reflection in the finish definition, except that in this sample scene, there's no background to reflect.

Example=5; Roundness
Example 5 illustrates how the roundness setting (CurvedPaving_BlockRoundness) affects the block shape.

   #declare CurvedPaving_Radius = 0.5;
   object {CurvedPaving("")}
  
   #declare CurvedPaving_BlockRoundness = 0.8;
   object {CurvedPaving("") translate -CurvedPaving_CentreToCentre*x}
  
   #declare CurvedPaving_BlockRoundness = 0;
   #declare CurvedPaving_MortarGap = 0.01;
   object {CurvedPaving("") translate CurvedPaving_CentreToCentre*x}

This setting only works with the default Superellipsoid blocks. If you specify "Box" or "Polygon" this setting has no affect.

The central block uses the default setting which sets roundness to 0.4.

The left hand block uses a roundness setting of 0.8 to give a more cobbled effect.

The right hand block uses a roundness setting of 0 to give completely square blocks. In this case the mortar gap (CurvedPaving_MortarGap) is increased to 0.01 to give a 1cm gap.

Example=6; Radius Setting
Example 6 provides a slightly more complex example to illustrate how to join sections of blockwork together when the radius of adjacent sections is different. Most real-world examples use a consistent radius for an entire paved area, but not all.

   #declare CurvedPaving_Radius = 0.5;
   #declare CurvedPaving_MortarGap = 0.0008;
   #declare Paving1 = CurvedPaving("")
   #local C2C1 = CurvedPaving_CentreToCentre;
   #local MinZ1 = z*min_extent(Paving1);
   object {Paving1 translate -MinZ1}
  
   #declare CurvedPaving_Radius = 1;
   #declare CurvedPaving_MortarGap = 0.004;
   #declare Paving2 = CurvedPaving("")
   #local C2C2 = CurvedPaving_CentreToCentre;
   #local MinZ2 = z*min_extent(Paving2);
   object {Paving2 translate -x*(C2C1+C2C2)/2-MinZ2}
  
   #declare CurvedPaving_Radius = 2.5;
   #declare CurvedPaving_MortarGap = 0.006;
   #declare Paving3 = CurvedPaving("")
   #local C2C3 = CurvedPaving_CentreToCentre;
   #local MinZ3 = z*min_extent(Paving3);
   object {Paving3 translate x*(C2C1+C2C3)/2-MinZ3}

As with example 2 you can use the 'CurvedPaving_CentreToCentre' variable, which is calculated by the 'CurvedPaving' macro, but this is recalculated with each call to the 'CurvedPaving' macro, so this example keeps a record of the value before calling the macro again. The actual centre to centre distance can then be calculated by taking half the centre to centre distance from one call plus half the centre to centre distance from the other.

Alignment of the 'seams' in the Z direction uses the standard POV-Ray function 'min_extent' to find the minimum extent of each section of blocks. It translates each section in -Z by that amount so that all 3 sections line up on the x-axis.

Example=7; Cutting to Shape
Example 7 renders two sections, sliced square using a CSG (Constructive Solid Geometry) intersection operation.

   #declare CurvedPaving_Rows = 60;
   intersection {
     union {
       object {CurvedPaving("") translate -x*CurvedPaving_CentreToCentre/2}
       object {CurvedPaving("") translate x*CurvedPaving_CentreToCentre/2}
     }
     box {<-0.67,-0.2,1><0.67,0.01,6> texture {CurvedPaving_ThisBlockTexture}}
   }

Most of the time when you want to add paving to a scene you want to apply it to an area with a very specific shape. In this example the shape is defined by creating a box that delimits the required section of paving. The POV-Ray 'intersection' operation is used to slice away everything that's outside the box.

Exactly the same technique can be used with more complex shapes built using CSG operations or with prism objects constructed from a spline. Various free utilities like the Spilin spline editor and the Inkscape SVG editor enable you to draw spline-based shapes and generate POV-Ray prism objects from those splines if you need to create really complex shapes.

Unfortunately, the cutaway_textures keyword doesn't work very well with complex CSG shapes, so in this example the texture 'CurvedPaving_ThisBlockTexture' is used with the cutting object and is therefore visible on the cut surfaces. This is actually the texture of the last block that was rendered, so it may not look right if you are using a more varied color range, but for most mottled blocks it should be quite a difficult defect to spot. It's obviously only something you need to worry about if the cut surface is visible, which is not always the case.

In this example the default normal and finish (as defined by the 'CurvedPaving' macro) are used to cut the ends of the otherwise smooth borders to the path and to give a texture to the mortar.

Example=8; Alternative Block Objects
Example 8 uses basically the same code as example 7 to render a section of footpath, but specifies the two alternative objects currently available for the two sections of pavement.

  object {CurvedPaving("Polygon") translate -x*CurvedPaving_CentreToCentre/2}
  object {CurvedPaving("Box") translate x*CurvedPaving_CentreToCentre/2}

The 'CurvedPaving_Block' macro is designed to make it easy to add new predefined block styles and one of the style options is to change the object from the default superellipsoid to an alternative object, such as a "Box" object or a "Polygon" object.

The example on the left uses the style parameter on the 'CurvedPaving' macro call to specify the "Polygon" object which creates wedge shaped polygons (with zero thickness). The example on the right uses a "Box" object, which is equivalent to a superellipsoid with no roundness. Both take slightly less time to render, but primarily illustrate the technique by which other shapes can be added.

The available object styles are:

  • "Polygon" (Left)
  • "Box" (Right)
  • "Superellipsoid" (The default)

Example=9; Colored Block Styles
Example 9 illustrates the use of predefined color styles. The 'CurvedPaving_Block' macro is designed to make it easy to add new predefined color and texture styles.

   object {CurvedPaving("RedBrick"  ) translate  <-CurvedPaving_CentreToCentre,0,1>}
   object {CurvedPaving("BlueBrick" ) translate  <0,0,1>}
   object {CurvedPaving("GreenBrick") translate  < CurvedPaving_CentreToCentre,0,1>}
   object {CurvedPaving("PinkBrick" ) translate -x*CurvedPaving_CentreToCentre}
   object {CurvedPaving("BuffBrick" ) }
   object {CurvedPaving("GreyBrick" ) translate  x*CurvedPaving_CentreToCentre}

This example renders six different swatches showing the predefined color settings that can be specified using the style parameter on the 'CurvedPaving' macro call.

The available color styles are:

  • "RedBrick" (Top Left)
  • "BlueBrick" (Top Centre)
  • "GreenBrick" (Top Right)
  • "PinkBrick" (Bottom Left)
  • "BuffBrick" (Bottom Centre)
  • "GreyBrick" (Bottom Right)

Example=10; Adjusting for Different Lighting Levels
Example 10 illustrates the use of brightness to adjust for alternative lighting levels. Different scene files can use very different lighting levels. The brightness setting allows you to compensate for this.

The image on the left was rendered with the default settings and a single full intensity light source.

The central image shows bleaching caused by color saturation when ten times as much light is added to the scene.

The image on the right is generated with:

   #declare CurvedPaving_Brightness = 0.1;
   object {CurvedPaving("")}

to redress the balance. The 'CurvedPaving_Brightness' variable is simply used as a multiplication factor for the color when the macro defines the block texture. It can therefore be used to counteract lighting variations from one scene to another.

Return to Table of Contents


Macros

The following macros are all contained in the 'curvedpaving.inc' file:

CurvedPaving macro
You call the CurvedPaving macro to create a section of paving. This is normally the only macro you need to call. The functionality is controlled through a series of variables, each of which has a default value, so you can generate the default section of paving with the following code:

 camera {orthographic location <0,2.8,1.74> look_at 1.75*z }
 light_source {<-10,20,-5>, rgb 1}
 #include "curvedpaving.inc"
 CurvedPaving("")

The CurvedPaving_Block macro has 1 parameter:
CurvedPaving_BlockType A string that can be used to specify a predefined block type (e.g. specific color settings or the object type to be generated). Pass an empty string into the macro ("") to use default settings or to use settings that you set inline within your code. The following set styles can be specified:
  • "Polygon"
  • "Box"
  • "Superellipsoid"
  • "RedBrick"
  • "BlueBrick"
  • "GreenBrick"
  • "PinkBrick"
  • "BuffBrick"
  • "GreyBrick"
See example 8 and example 9 above for illustrations of these style settings.

CurvedPaving_ArcOfBlocks macro
The CurvedPaving_ArcOfBlocks macro is used to create an arc of blocks based upon the specified settings. This macro is repeatedly called by the 'CurvedPaving' macro to create a series if adjacent arcs. This macro calls the 'CurvedPaving_Block' macro to draw each block.

You won't normally need to invoke this macro directly. It is called indirectly via the 'CurvedPaving' macro.

The CurvedPaving_Block macro has 1 parameter:
CurvedPaving_BlockType A string that can be used to specify a predefined block type (e.g. specific color settings or the object type to be generated). Pass an empty string into the macro ("") to use default settings. See example 8 and example 9 above for illustrations of the available style settings.

CurvedPaving_Block macro
The CurvedPaving_Block macro is used to create an individual block based upon the specified settings. This macro is called repeatedly by the 'CurvedPaving_ArcOfBlocks' macro to draw each of the blocks that go to make up an arc.

You won't normally need to invoke this macro directly if you are using the 'CurvedPaving' macro because this macro is called indirectly from that macro. However, you may wish to create a macro of your own that defines a different pattern, in which case you can call this macro to draw the individual blocks.

The CurvedPaving_Block macro can easily be tailored to add 'predefined' colors or shapes to those supplied. You can do this by adding a new '#case' clause to one of the two '#switch' statements. This usually only involves adding a couple of lines using basic coding elements, such as declarations of colors etc. and subsequently enables you to refer to your new style of block by name whenever you wish to use it in the future.

The CurvedPaving_Block macro has 5 parameters:
CurvedPaving_TopLeft A 3D vector defining the coordinates of the top left corner of the space into which this block needs to fit.
CurvedPaving_TopRight A 3D vector defining the coordinates of the top right corner of the space into which this block needs to fit.
CurvedPaving_BottomRight A 3D vector defining the coordinates of the bottom right corner of the space into which this block needs to fit.
CurvedPaving_BottomLeft A 3D vector defining the coordinates of the bottom left corner of the space into which this block needs to fit.
CurvedPaving_BlockType A string that can be used to specify a predefined block type (e.g. specific color settings or the object type to be generated). Pass an empty string into the macro ("") to use default settings. See example 8 and example 9 above for illustrations of the available style settings.

CurvedPaving_Undef macro
The CurvedPaving_Undef macro can be used to undefine all of the key control variables between calls to the 'CurvedPaving' macro. This is often not necessary, but can be useful if you have set a lot of control variables for one call and you want to return most of those settings to their default values the next time the 'CurvedPaving' macro is called. This can also be useful if you are using named block types as it avoids you having to work out which variables were set during the first call. By undefining them all between macro calls you can avoid that the settings for one predefined block type interfere with the next.

The CurvedPaving_Undef macro has no parameters:

Return to Table of Contents


Control Variables

The following variables are used to control the operation of the 'CurvedPaving' macro. Each has a default setting, so you only need to specify settings that you wish to override.
VariableDescription
CurvedPaving_Radius Decimal value used by the CurvedPaving macro to control the radius of the arcs of blocks that make up the section of paving. The default value is 1 POV-Ray unit and is intended to represent a distance of 1 metre. The centre of the first arc of blocks will start this distance along the +Z axis from the origin.
CurvedPaving_BlockDepth Decimal value used by the CurvedPaving macro to control the horizontal dimensions of the blocks. This is actually the distance along the +Z axis from one arc of blocks to the next. The default value is 0.1 POV-Ray unit and is intended to represent a distance of 10 centimetres, giving 10 rows of blocks per metre at the centre of the arc.
CurvedPaving_Rows Integer value used by the CurvedPaving macro to control the number of rows of blocks to generate. The default value is 20 which give 20 rows/arcs of blocks.
CurvedPaving_MortarGap Decimal value used by the CurvedPaving macro to control the average space between blocks. The generated blocks are defined to fit into the space calculated using the 'CurvedPaving_BlockDepth' setting with half this gap all around them. The default value is 0.0001 which represents 0.01mm to produce blocks that butt right up against each other. Because the Superellipsoid shape is usually used to generate rounded blocks, the space available for mortar will actually appear to be substantially larger. If you use the "Box" or "Polygon" shapes you should increase this value to about 0.01 to give a 1cm gap because these shapes don't have rounded edges (see example 8).
CurvedPaving_BlockThickness Decimal value used by the CurvedPaving macro to control the thickness of the blocks. The default value is 0.08 which represents 8cm from the top surface to the bottom surface.
CurvedPaving_BlockRoundness Decimal value between 0 and 1 used by the CurvedPaving macro to control the roundness of the blocks. The default value is 0.4 which produces a block with a distinctly rounded edge. A value of 0 gives square edges and 1 makes the blocks spherical.
CurvedPaving_MinColor 3D RGB color vector used by the CurvedPaving macro to control the selection of colors. This vector provides the minimum red, green and blue values. The default value is <0.6,0.3,0.3> which makes the minimum color a dark red. Each color element is generated independently, so a minimum of <0,0,0> with a maximum of <1,1,1> will permit any valid color to be selected. See example 2 for an illustration of this setting.
CurvedPaving_MaxColor 3D RGB color vector used by the CurvedPaving macro to control the selection of colors. This vector provides the maximum red, green and blue values. The default value is <0.75,0.35,0.35> which makes the maximum color a medium red. Each color element is generated independently, so a minimum of <0,0,0> with a maximum of <1,1,1> will permit any valid color to be selected.See example 2 for an illustration of this setting.
CurvedPaving_Contrast Decimal value between 0 and 1 used by the CurvedPaving macro to control the degree by which randomly selected colors can be randomnly darkened. The default value is 0.8 which results in each generated color value being multiplied by a random factor between 1 and 0.5. A setting of 0 results in the colors being within the range specified using CurvedPaving_MinColor and CurvedPaving_MaxColor. A setting of 1 means that randomly selected blocks could be darkened all the way down to black.

Most real blockwork consists of a base color range with some blocks being a darker version of that same limited range. This setting allows that sort of control to be applied. See example 3 for an illustration of this setting.

CurvedPaving_Brightness Decimal value used by the CurvedPaving macro to control the overall brightness of the block texture. The default value of 1 doesn't adjust the colors at all.

This setting is designed to accommodate the hugely different lighting settings used in POV-Ray scene files. Some people use a lot of light and dim colors. Others use low light levels and bright colors. The default settings and most of the examples use a single, full light source. If your scene uses more light you can reduce this value. If you use less light in your scene you can increase this value. See example 10, which uses a light source that is 10 times brighter, setting this value to 0.1 to compensate and avoid color saturation artifacts.

CurvedPaving_Normal A normal definition used by the CurvedPaving macro to define a texture for the blocks. The default normal uses a granite normal scaled to 0.1. See example 4, which demonstrates how to override this default by specifying an agate normal for the blocks on the left.
CurvedPaving_Finish A finish definition used by the CurvedPaving macro to define a texture for the blocks. The default finish uses a phong setting of 0. See example 4, which demonstrates how to override this default by specifying a phong setting of 1 for the blocks on the right.

Adding phong or reflection to the finish setting can provide a simple way of emulating wet blocks.

CurvedPaving_RandomSeed A random number seed used internally to control the randomisation sequence. Normally you don't need to alter this value as it is initialised with the first macro call.
CurvedPaving_ThisBlockTexture A read-only texture setting that returns the last texture definition used to create a block. In fact you can set this texture, but it has no affect on the operation of the macro which will simply overwrite it on each call.

This can be handy when cutting a section of blocks using CSG (Constructive Solid Geometry) operations to apply a credible texture to the cut surface (See example 7)

CurvedPaving_CentreToCentre A read-only variable that returns the distance in X that you need to translate one panel to the left or right to join two equally sized panels seamlessly together. In fact you can set this variable, but it has no affect on the operation of the macro which will simply overwrite it on each call.

To join two panels of different radii, take half the value returned from one macro call and half the value returned by the second. (See example 6)

Return to Table of Contents