IsoCSG Library
created by Christoph Hormann
http://www.imagico.de/

'iso_csg.inc' - Main include file

This file contains macros for the basic CSG functions, shapes and transformations.

The main macros included in the file are the following:



Description of the macros

The CSG macros

These macros implement the basic CSG operations. Since POV-Ray does not allow optional parameters in macros there are separate versions for combining 2, 3, 4 and 5 functions. More functions can be CSGed using a combination of those macros.

Note that for better performance it's often a good idea to divide the shape into several isosurface objects and combine them with conventional CSG.

IC_Merge2()

Merge2 sample (4k)

Creates a merge of two functions.

parameters:

example:

  #declare fn_1=
    IC_Merge2 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>)
    )

IC_Merge3()

Merge3 sample (5k)

Creates a merge of three functions.

parameters:

example:

  #declare fn_1=
    IC_Merge3 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<0,0,-1.6>, <0,0,1.6>, 0.6)
    )

IC_Merge4()

Merge4 sample (5k)

Creates a merge of four functions.

parameters:

example:

  #declare fn_1=
    IC_Merge4 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<0,0,-1.6>, <0,0,1.6>, 0.6),
      IC_Rotate (IC_Torus (1, 0.2), 90*x)
    )

IC_Merge5()

Merge5 sample (5k)

Creates a merge of five functions.

parameters:

example:

  #declare fn_1=
    IC_Merge5 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<0,0,-1.6>, <0,0,1.6>, 0.6),
      IC_Rotate (IC_Torus (1, 0.2), 90*x),
      IC_Cone (<0,0,0>, 0, <0,-1.6,0>, 0.5)
    )

IC_Merge_Array()

Creates a merge of an array of functions. An arbitrary number of functions can be merged this way.

parameters:

IC_Intersection2()

Intersection2 sample (4k)

Creates a intersection of two functions.

parameters:

example:

  #declare fn_1=
    IC_Intersection2 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>)
    )

IC_Intersection3()

Intersection3 sample (4k)

Creates a intersection of three functions.

parameters:

example:

  #declare fn_1=
    IC_Intersection3 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<-1.6,0,0>, <1.6,0,0>, 0.7)
    )

IC_Intersection4()

Intersection4 sample (4k)

Creates a intersection of four functions.

parameters:

example:

  #declare fn_1=
    IC_Intersection4 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<-1.6,0,0>, <1.6,0,0>, 0.7),
      IC_Cone (<-2,0,0>, 0, <2,0,0>, 1.8)
    )

IC_Intersection5()

Intersection5 sample (4k)

Creates a intersection of five functions.

parameters:

example:

  #declare fn_1=
    IC_Intersection5 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<-1.6,0,0>, <1.6,0,0>, 0.7),
      IC_Cone (<-2,0,0>, 0, <2,0,0>, 1.8),
      IC_Plane (z, 0)
    )

IC_Intersection_Array()

Creates an intersection of an array of functions. An arbitrary number of functions can be combined this way.

parameters:

IC_Difference2()

Difference2 sample (5k)

Creates a difference of two functions.

parameters:

example:

  #declare fn_1=
    IC_Difference2 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>)
    )

IC_Difference3()

Difference3 sample (5k)

Creates a difference of three functions.

parameters:

example:

  #declare fn_1=
    IC_Difference3 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<0,0,-1.6>, <0,0,1.6>, 0.6)
    )

IC_Difference4()

Difference4 sample (5k)

Creates a difference of four functions.

parameters:

example:

  #declare fn_1=
    IC_Difference4 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<0,0,-1.6>, <0,0,1.6>, 0.6),
      IC_Rotate (IC_Torus (1, 0.2), 90*x)
    )

IC_Difference5()

Difference5 sample (6k)

Creates a difference of five functions.

parameters:

example:

  #declare fn_1=
    IC_Difference5 (
      IC_Sphere (<0,0,0>, 1),
      IC_Box (<-1.6,-0.6,-0.6>, <1.6,0.6,0.6>),
      IC_Cylinder (<0,0,-1.6>, <0,0,1.6>, 0.6),
      IC_Rotate (IC_Torus (1, 0.2), 90*x),
      IC_Cone (<0,0,0>, 0, <0,-1.6,0>, 0.5)
    )

IC_Difference_Array()

Creates a difference of an array of functions. An arbitrary number of functions can be combined this way.

parameters:

IC_Inverse()

Inverts a function.

parameters:

example:

  #declare fn_1=
    IC_Inverse (
      IC_Sphere (<0,0,0>, 1)
    )

The shape macros

These macros create the basic CSG shapes known from POV-Ray. The parameters of the macros are corresponding to those of the POV-Ray shapes. They can be combined with any other user defined functions.

IC_Plane()

Plane sample (2k)

Creates a plane shape in form of an isosurface function. Syntax is equivalent to the POV-Ray plane object.

parameters:

example:

  #declare fn_1 = IC_Plane(z, 0)

IC_Sphere()

Sphere sample (3k)

Creates a sphere shape in form of an isosurface function. Syntax is equivalent to the POV-Ray sphere object.

parameters:

example:

  #declare fn_1 = IC_Sphere(<0,0,0>, 1)

IC_Box()

Box sample (3k)

Creates a box shape in form of an isosurface function. Syntax is equivalent to the POV-Ray box object.

parameters:

example:

  #declare fn_1 = IC_Box (<-0.8,-0.8,-0.8>, <0.8,0.8,0.8>)

IC_Torus()

Torus sample (3k)

Creates a torus shape in form of an isosurface function. Syntax is equivalent to the POV-Ray torus object.

parameters:

example:

  #declare fn_1 = IC_Torus (0.8, 0.2)

IC_Cylinder()

Cylinder sample (3k)

Creates a cylinder shape in form of an isosurface function. Syntax is equivalent to the POV-Ray cylinder object.

parameters:

example:

  #declare fn_1 = IC_Cylinder (-x, x, 0.8)

IC_Cylinder_Hole()

Cylinder_Hole sample (4k)

Creates a cylinder shape with hole in form of an isosurface function.

parameters:

example:

  #declare fn_1 = IC_Cylinder_Hole (-x, x, 0.8, 0.4)

IC_Cone()

Cone sample (3k)

Creates a cone shape in form of an isosurface function. Syntax is equivalent to the POV-Ray cone object.

parameters:

example:

  #declare fn_1 = IC_Cone (-x, 0.2, x, 0.8)

IC_Superellipsoid()

Superellipsoid sample (3k)

Creates a superellipsoid shape in form of an isosurface function. Syntax is equivalent to the POV-Ray superellipsoid object.

parameters:

example:

  #declare fn_1 = IC_Superellipsoid (0.2, 0.8)

IC_Sor()

Sor sample (4k)

Creates a sor like shape in form of an isosurface function. The points in the array passed as the first parameter are equivalent to those in the POV-Ray sor object. The second parameter works like the optional open keyword of that object.

parameters:

example:

  #declare Point_Array=array[12] {
    <0.2, -1.6>
    <0.2, -1.5>
    <0.1, -1.2>
    <1.0, -0.6>
    <0.1, 0.0>
    <0.1, 0.1>
    <0.6, 0.2>
    <0.3, 0.4>
    <0.5, 0.6>
    <0.3, 0.8>
    <0.2, 1.1>
    <0.2, 1.7>
  }

  #declare fn_1 = IC_Sor (Point_Array, IC_Close)

IC_Round_Box()

Round_Box sample (3k)

Creates a rounded box shape in form of an isosurface function. It works like the Round_Box() macro in shapes.inc.

parameters:

example:

  #declare fn_1 = IC_Round_Box (<-0.8,-0.8,-0.8>, <0.8,0.8,0.8>, 0.2)

IC_Triangle()

Triangle sample (3k)

Creates a triangle shape in form of an isosurface function. with a certain thickness.

parameters:

example:

  #declare fn_1 = IC_Triangle(<-0.5, 1, -0.5>, <0, -1, -0.5>, <1, 1, 0.8>, 0.1)

IC_Heightfield()

Heightfield sample (3k)

Creates a height_field shape in form of an isosurface function with a certain intensity of the height variation. The intensity value works like a vertical scaling applied to a height_field object. It is more efficient to apply a scaling in the function than afterwards.

The macro tries to automatically determine the file type from the file name. If this is not successful it assumes a png image.

Note: POV-Ray handles image files differently when using them in heightfields and in image maps under certain circumstances. Since this macro uses image maps to create the surface results differ from a converntional heightfield in those cases.

parameters:

example:

  #declare fn_1 = IC_Heightfield("image.png", 0.1)

IC_Heightfield_Function()

Heightfield_Function sample (3k)

Like IC_Heightfield() but with a function describing the height variation. The function is evaluated in the x-y-plane between 0 and 1.

parameters:

example:

  #declare fn_1 = IC_Heightfield_Function( function { 0.5 + sin(x*8)*sin(y*8)*0.2 } )

IC_HF_Sphere()

HF_Sphere sample (3k)

Creates a spherical heightfield similar to the HF_Sphere macro in shapes.inc. The image is wrapped around the sphere with the poles in z-direction and the surface is displaced accordingly. See also the description of the IC_Heightfield() macro.

parameters:

example:

  #declare fn_1 = IC_HF_Sphere(1, "image.png", 0.2)

IC_HF_Sphere_Function()

HF_Sphere_Function sample (3k)

Like IC_HF_Sphere() but with a function describing the height variation. The function is evaluated in the x-y-plane between 0 and 1.

parameters:

example:

  #declare fn_1 = IC_HF_Sphere_Function(1, function { 0.5 + sin(x*8)*sin(y*8)*0.2 } )

IC_HF_Cylinder()

HF_Cylinder sample (3k)

Creates a spherical heightfield similar to the HF_Cylinder macro in shapes.inc. The image is wrapped around the cylinder with the cylinder axis in z-direction and the surface is displaced accordingly. See also the description of the IC_Heightfield() macro.

parameters:

example:

  #declare fn_1 = IC_HF_Cylinder(1, 2, "image.png", 0.2)

IC_HF_Cylinder_Function()

HF_Cylinder_Function sample (3k)

Like IC_HF_Cylinder() but with a function describing the height variation. The function is evaluated in the x-y-plane between 0 and 1.

parameters:

example:

  #declare fn_1 = IC_HF_Cylinder_Function(1, function { 0.5 + sin(x*8)*sin(y*8)*0.2 } )

The torus macros

These macros generate shapes based on a torus like geometry.

IC_Shaped_Torus()

Shaped_Torus sample (6k)

Creates a torus like shape with a cross section defined by a function.

The cross section function is evaluated in the x-y-plane.

parameters:

example:

#declare fn_Cross=
  IC_Merge3(
    IC_Cylinder(<0.1-0.30><-0.10.30>0.05),
    IC_Cylinder(<-0.0600><0.30.30>0.03),
    IC_Sphere(<0.30.30>0.07)
  )

#declare fn_1=IC_Shaped_Torus(fn_Cross, 0.66)

IC_Fan()

Fan sample (4k)

Creates a segment of a torus across a certain angle.

parameters:

example:

#declare fn_1=IC_Fan(0.70.2220)

IC_Shaped_Fan()

Shaped_Fan sample (4k)

Like IC_Fan() but with the cross section defined by a function. The function is evaluated in the x-y-plane.

parameters:

example:

#declare fn_Cross=
  IC_Merge3(
    IC_Cylinder(<0.1-0.30><-0.10.30>0.05),
    IC_Cylinder(<-0.0600><0.30.30>0.03),
    IC_Sphere(<0.30.30>0.07)
  )

#declare fn_1=IC_Shaped_Fan(fn_Cross, 0.66220)

IC_Arc()

Arc sample (4k)

Like IC_Fan() but with the start and end angle as parameters instead of the angle range.

parameters:

example:

#declare fn_1=IC_Arc(0.70.20220)

IC_Shaped_Arc()

Shaped_Arc sample (4k)

Like IC_Arc() but with the cross section defined by a function. The function is evaluated in the x-y-plane.

parameters:

example:

#declare fn_Cross=
  IC_Merge3(
    IC_Cylinder(<0.1-0.30><-0.10.30>0.05),
    IC_Cylinder(<-0.0600><0.30.30>0.03),
    IC_Sphere(<0.30.30>0.07)
  )

#declare fn_1=IC_Shaped_Fan(fn_Cross, 0.660220)

IC_Torus_Spline()

Torus_Spline sample (4k)

Creates a sphere_sweep like shape of torii defined by an array of points.

parameters:

example:

#declare Points=array[5{
  <0.25-0.150.9>,
  <0.250.60.8>,
  <0.00.90.15>,
  <-0.250.9-0.25>,
  <0.25-0.6-0.7>
}
#declare fn_1=IC_Torus_Spline(0.09, Points, x)

The blob macros

With these macros you can create blob shapes. In contrast to the POV-Ray blob object you can also blob arbitrary user defined functions, not only cylinders and spheres.

There are two types of macros concerning blobs, those generating blob components:

and those combining the blob components to a blob shape:

Apart from using a macro you can also combine the components by simply adding them.

IC_BlobSphere()

BlobSphere sample (9k)

Creates a spherical blob component. Like in the components of the POV-Ray blob object there is an additional parameter to specify the component strength.

parameters:

example:

  #declare fn_1 = IC_BlobSphere (0, 1, 1)

IC_BlobCylinder()

BlobCylinder sample (9k)

Creates a cylindrical blob component. Like in the components of the POV-Ray blob object there is an additional parameter to specify the component strength.

parameters:

example:

  #declare fn_1 = IC_BlobCylinder (<-1, 0, 0>, <1, 0, 0>, 1, 1)

IC_BlobShape()

BlobShape sample (5k)

Creates a blob component from an arbitrary user defined function. Function values below zero are clipped. This macro opens a lot of new possibilities not present in the POV-Ray blob object.

The RadiusVal value in this case has a more general meaning but it works similar to the radius in the spherical and cylindrical component.

parameters:

example:

  #declare fn_1 = IC_BlobShape (IC_Plane (-x, 0), 0.25, 1)

IC_Blob2()

Blob2 sample (9k)

Creates a blob shape made of two components. The components should be created by one of the blob components creation macros.

parameters:

example:

  #declare fn_1 =
    IC_Blob2 (
      IC_BlobSphere ( 0.75*x, 1.2, 1),
      IC_BlobSphere (-0.75*x, 1.2, 1),
      0.7
    )

IC_Blob3()

Blob3 sample (9k)

Creates a blob shape made of three components. The components should be created by one of the blob components creation macros.

parameters:

example:

  #declare fn_1 =
    IC_Blob3 (
      IC_BlobSphere ( 0.75*x, 1.18, 1),
      IC_BlobSphere (-0.75*x, 1.18, 1),
      IC_BlobSphere (-0.4*y, 0.4, 1),
      0.7
    )

IC_Blob4()

Blob4 sample (8k)

Creates a blob shape made of four components. The components should be created by one of the blob components creation macros.

parameters:

example:

  #declare fn_1 =
    IC_Blob3 (
      IC_BlobSphere ( 0.75*x, 1.18, 1),
      IC_BlobSphere (-0.75*x, 1.18, 1),
      IC_BlobSphere (-0.4*y, 0.4, 1),
      IC_BlobCylinder (<-0.75, 0, 0.6>, <0.75, 0, 0.6>, 0.35, 1),
      0.7
    )

IC_Blob5()

Blob5 sample (8k)

Creates a blob shape made of five components. The components should be created by one of the blob components creation macros.

parameters:

example:

  #declare fn_1 =
    IC_Blob3 (
      IC_BlobSphere ( 0.75*x, 1.18, 1),
      IC_BlobSphere (-0.75*x, 1.18, 1),
      IC_BlobSphere (-0.4*y, 0.4, 1),
      IC_BlobCylinder (<-0.75, 0, 0.6>, <0.75, 0, 0.6>, 0.35, 1),
      IC_BlobCylinder (<0, -0.75, 0.6>, <0, 0.75, 0.6>, 0.35, 1),
      0.7
    )

IC_Blob_Array()

This macro combines an array of blob component functions to a blob shape.

parameters:

example:

  #declare Blob_Array = array[3]
  #declare Blob_Array[0] = IC_BlobSphere ( 0.75*x, 1.18, 1)
  #declare Blob_Array[1] = IC_BlobSphere (-0.75*x, 1.18, 1)
  #declare Blob_Array[2] = IC_BlobSphere (-0.4*y, 0.4, 1)

  #declare fn_1 = IC_Blob_Array (Blob_Array, 0.7)

Manually combining blob components

Blob components can be also be combined manually by simply adding the functions..

example:

  #declare fn_1 =
    function {
        fn_Component_1 (x,y,z)
      + fn_Component_2 (x,y,z)
      + fn_Component_3 (x,y,z)
      + fn_Component_4 (x,y,z)

      + Threshold
    }

IC_Blob_Linear()

Blob_Linear sample (3k)

This macro inverts the transformation applied to the functions for creating the blob and generates a function approximately representing the linear distance to the surface when the original component functions also worked this way.

Note the function is only linear up to a certain distance from the shape which depends on the RadiusVal value of the blob. Further away from the surface the function value stays constant.

parameters:

example:

  #declare fn_1 = IC_Blob_Linear (fn_Blob, 1.0, 1.6, 0.7)

The exponential blob macros

These macros implement a different method of 'blobbing' shapes as described in the POV-Ray manual. It often produces more appealing results and designing shapes can be more intuitive. Other than the IC_Blob* macros these take shape function generated by the IsoCSG macros or other functions straight away without an IC_BlobShape() macro.

The following macros are for combining shapes to a blob:

IC_EBlob2()

EBlob2 sample (7k)

Creates an exponential blob shape made of two components. The components can be arbitrary IsoCSG functions.

parameters:

example:

  #declare fn_1 =
    IC_EBlob2 (
      IC_Sphere ( 0.6*x, 0.65),
      IC_Sphere (-0.6*x, 0.65),
      0.001
    )

IC_EBlob3()

EBlob3 sample (7k)

Creates a blob shape made of three components. The components can be arbitrary IsoCSG functions.

parameters:

example:

  #declare fn_1 =
    IC_EBlob3 (
      IC_Sphere ( 0.65*x, 0.65),
      IC_Sphere (-0.65*x, 0.65),
      IC_Sphere (-0.75*y, 0.3),
      0.001
    )

IC_EBlob4()

EBlob4 sample (7k)

Creates a blob shape made of four components. The components can be arbitrary IsoCSG functions.

parameters:

example:

  #declare fn_1 =
    IC_EBlob4 (
      IC_Sphere ( 0.65*x, 0.65),
      IC_Sphere (-0.65*x, 0.65),
      IC_Sphere (-0.75*y, 0.3),
      IC_Cylinder (<-0.75, 0, 0.7>, <0.75, 0, 0.7>, 0.2),
      0.001
    )

IC_EBlob5()

EBlob5 sample (7k)

Creates a blob shape made of five components. The components can be arbitrary IsoCSG functions.

parameters:

example:

  #declare fn_1 =
    IC_EBlob5 (
      IC_Sphere ( 0.65*x, 0.65),
      IC_Sphere (-0.65*x, 0.65),
      IC_Sphere (-0.75*y, 0.3),
      IC_Cylinder (<-0.75, 0, 0.7>, <0.75, 0, 0.7>, 0.2),
      IC_Cylinder (<0, -0.75, 0.7>, <0, 0.75, 0.7>, 0.1),
      0.001
    )

IC_EBlob_Array()

This macro combines an array of blob component functions to a blob shape.

parameters:

example:

  #declare Blob_Array = array[3]
  #declare Blob_Array[0] = IC_Sphere ( 0.65*x, 0.65)
  #declare Blob_Array[1] = IC_Sphere (-0.65*x, 0.65)
  #declare Blob_Array[2] = IC_Sphere (-0.75*y, 0.3)

  #declare fn_1 = IC_EBlob_Array (Blob_Array, 0.001)

IC_EBlob_Linear()

EBlob_Linear sample (7k)

This macro inverts the transformation applied to the functions for creating the blob and generates a function approximately representing the linear distance to the surface when the original component functions also worked this way.

Note the function is only linear up to a certain distance from the shape which depends on the Threshold value of the blob. Further away from the surface the function value stays constant.

example:

  #declare fn_1 = IC_EBlob_Linear (fn_Blob, 0.001)

The transform macros

These macros can be used to transform IsoCSG functions just like conventional shapes.

IC_Transform()

Transforms a given isosurface function with a transform and returns the resulting function.

parameters:

example:

  #declare fn_1 = IC_Transform (IC_Torus (0.8, 0.2), transform { rotate 45*z })

IC_Translate()

Translates a given isosurface function by a vector and returns the resulting function.

parameters:

example:

  #declare fn_1 = IC_Translate (IC_Sphere (0, 1), 1.5*z)

IC_Scale()

Scales a given isosurface function by a vector and returns the resulting function.

parameters:

example:

  #declare fn_1 = IC_Scale (IC_Sphere (0, 1), <1,1,2>)

IC_ScaleC()

Range corrected version of the scale macro. With asymmetric scaling the values are corrected with the mean of the scale vector.

parameters:

example:

  #declare fn_1 = IC_Scale (IC_Sphere (0, 1), <1,1,2>)

IC_RotateR()

Rotates a given isosurface function and returns the resulting function. Angles given in radians.

parameters:

example:

  #declare fn_1 = IC_RotateR (IC_Box (-1, 1), pi*0.25*z)

IC_Rotate()

Rotates a given isosurface function and returns the resulting function. Angles given in degrees.

parameters:

example:

  #declare fn_1 = IC_Rotate (IC_Box (-1, 1), 45*z)

IC_Reorient()

Applies a Reorient() transform to a given isosurface function.

parameters:

example:

  #declare fn_1 = IC_Reorient (IC_Box (-1, 1), x, x+y)

IC_AxisRotate()

Applies a AxisRotate() transform to a given isosurface function.

parameters:

example:

  #declare fn_1 = IC_AxisRotate (IC_Box (-1, 1), x+y, 35)

The helper macros

These macros can be useful for working with IsoCSG functions.

IC_Threshold()

IC_Threshold sample (4k)

Changes the threshold of a function by subtracting a value.

parameters:

example:

  #declare fn_1 = IC_Threshold (IC_Box (-1, 1), 0.3)

IC_Displace()

IC_Displace sample (4k)

Displaces the surface with a second function.

parameters:

example:

  #declare fn_1 = IC_Displace (
    IC_Box (-1, 1),
    function { f_noise3d(x, y, z)*0.3 }
  )