Param.inc

© Mike Williams 2002,2003,2004

Up | Previous: Parametric Equations | Next: Approximation Macro | Alphabetical Index

Mesh2 vs parametrics

Parametric equations are very slow in POV 3.5, but Ingo Janssen has produced an include file which accepts a syntax quite similar to that of parametric equations and produces a mesh2 object. Ingo's technique can usually produce images that are indistinguishable from real parametric surfaces in a fraction of the time.

Param.inc and associated files can be found on the MMGM Google Code webpage. There are several advantages to this technique:

  • It's very much faster.
  • The mesh2 data can be written to a file, so it need only be parsed once making it even faster to re-render the scene or to have more than one copy of the surface in a scene.
  • The mesh2 data is prepared with UV mapping information, so a UV mapped texture can be applied. This is not the case for parametric surfaces or isosurfaces.
  • param.inc can be passed macros instead of functions. This allows the use of the float functions and vector functions that are not available in used defined functions.
param06.jpg

ingo06.jpg

ingo06b.jpg

The top image was created as a POV 3.5 parametric surface. On my machine it took over 12 minutes to render.

The second image was created with the "param.inc" file as a mesh2 object. On my machine it took 5 seconds to render. I can't tell the difference between the resulting images.

I've added a grid to the third image to show the edges of the mesh.

The syntax of the POV 3.5 parametric isosurface is:


#declare Fx = function {A*cos(u)}
#declare Fy = function {B*cos(v)+A*sin(u)}
#declare Fz = function {C*sin(v)}

parametric {
  function {Fx(u,v,0)}
  function {Fy(u,v,0)}
  function {Fz(u,v,0)}
      <0,0>,<2*pi,2*pi>
  contained_by{box{<-R,-R,-R>,<R,R,R>}}
  precompute 18, x,y,z}
The syntax for the mesh2 object is:

#declare Fx = function(u,v) {A*cos(u)}
#declare Fy = function(u,v) {B*cos(v)+A*sin(u)}
#declare Fz = function(u,v) {C*sin(v)}

#include "param.inc"

object {
  Parametric(Fx,Fy,Fz,<0,0>,<2*pi,2*pi>,30,30,"")
}
When used this way, param.inc requires
  • The three parametric functions Fx(), Fy() and Fz(), each of which must be functions of two variables.
  • The min and max values of u and v.
  • The number of steps into which the u and v ranges are divided.
  • Optionally a filename for saving/loading the mesh data.

For details of the options, read the comments inside Ingo's param.inc file.

uvtorus.jpg

uvtorustwist.jpg

Here's an example of one way of using uv mapping on a mesh2 created with param.inc.

The first surface is a simple torus

#declare Fx = function(u,v){cos(u)*(R1 + R2*cos(v))}
#declare Fy = function(u,v){sin(u)*(R1 + R2*cos(v))}
#declare Fz = function(u,v){R2*sin(v)}
I've used a layered texture. The bottom layer is green and white stripes in the u direction, and the top layer is red and white stripes in the v direction. These are actually the same u and v that occur in the functions that specify the surface.

In this case, u and v are both in the range 0 to 2*pi, but I want an integral number of stripes (otherwise I get one stripe with a different width) so I've multiplied the texture parameters by 7/pi to get 14 stripes instead of 2*pi stripes.

  texture {
    pigment { uv_mapping 
      function{u*7/pi}
      colour_map {[0.5 rgb y][0.5 rgb 1]}
    }
  }
  texture {
    pigment { uv_mapping 
      function{v*7/pi}
      colour_map {[0.4 rgb x][0.4 rgbt 1]}
    }
    finish {
      phong 0.5
      phong_size 10
    }
  }
In the second example, the textures are still in the u and v directions. It's the actual surface that's twisted.
#declare Fx = function(u,v){cos(u-v)*(R1 + R2*cos(v+u))}
#declare Fy = function(u,v){sin(u-v)*(R1 + R2*cos(v+u))}
#declare Fz = function(u,v){R2*sin(v+u)}
Without the uv mapped textures, these two surfaces look identical.
moebius.jpg
Moebius strip with discontinuous pigment

moebius2.jpg
Continuous symmetrical pigment

moebius3.jpg
Continuous asymmetric pigment

If the object you are attempting to uvmap has a place where the inside meets the outside, like in a Moebius strip, then you may see a discontinuity in the mapping. To fix this, you could use a texture that is symmetrical, like this:
pigment { uv_mapping 
  function{v*3/0.6}
  colour_map {[0.2 rgb x][0.2 rgbt 1]
              [0.8 rgbt 1][0.8 rgb x]}
}
Or, if you really want an asymmetric texture you could paint the interior_texture with a copy of the same texture that is inverted. The easiest way to do this is to apply scale -1 to the interior_texture. In some cases it may be necessary to use scale <-1,1,1> or scale <1,-1,1>

Download a zip file containing the POV source files for scenes on this page, and scenes equivalent to those on the previous page, but using Ingo Janssen's param.inc file.

Up | Previous: Parametric Equations | Next: Approximation Macro | Alphabetical Index