/* This help section is best viewed with a monospaced font (such as 'Lucida Console'). ________________________ | RPI.inc | | | | Randomized Orientation | | of Pattern Instances | | | | 2011 Samuel Benge | ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ _______ | Intro | ŻŻŻŻŻŻŻ RPI is an experimental method for seamlessly tiling 2D space with randomly oriented grayscale pigments. Its purpose is to cover an infinite area with patterns, functions or images while avoiding obvious repetition. It's best used when applied to planar surfaces, though it can be treated as a 3D pigment as well. This implementation is not perfect! If any of you like it enough to see it developed further and have found glaring errors, then by all means speak up! ____________ | The Macros | ŻŻŻŻŻŻŻŻŻŻŻŻ RPI( Pigment ) ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ Pigment = input pigment Proper use of 'Pigment' is the most important part of this include file. This is the pigment that will be copied across space. It should occupy an area between <-1,-1,-infinity> and <1,1,infinity>, though slightly larger pigments may be used (a factor of 1.4 was found to show only minor artifacts). You can use the provided 'RPI_DefaultPigment' for testing this macro (see default.pov). RPI() returns a function that can be used directly in a pigment statement. It maps the x/y plane and is oriented along the z-axis. Your pigment's depth will be preserved, so RPI() can be used as a 3D pigment as well. RPI_PTransform( Pigment, TwistAmt, ScaleAmt, FadeAmt ) ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ Pigment = any pigment TwistAmt = amount of twisting (float) ScaleAmt = scale variation (float) FadeAmt = fade variation (float) RPI_PTransform() returns a pigment. This macro transforms a pigment in various ways. Every transform is performed along the z-axis. The end result is randomized orientation for every pigment instance. Try not to use every transform if you don't need it, as each one is costly. For instance, if you set "TwistAmt' to 0.0 the macro will ignore the twisting calculations, and the pigment will take less time to render. RPI_CompileImages( ImageBaseName, NImages ) ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ ImageBaseName = a string containing the base image name without the .png affix (eg. "images" or "images0") NImages = number of images to use (int) This macro will take a series of consecutively-numbered PNG images and place them all into one tidy gradient z pattern for direct use within the RPI macro. You can use up to 128 images, provided all of your images are numbered and named properly. It will not look very good when mapped to non-planar surfaces. ___________ | Variables | ŻŻŻŻŻŻŻŻŻŻŻ RPI_DefaultPigment ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ Use this for testing the RPI macro. ______________________ | Ideal Input Pigments | ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ 1) pigment{ cylindrical rotate x*90 } 2) pigment{ boxed warp{planar} } 3) pigment{ boxed warp{planar} pigment_map{ [0 rgb 0] [1 image_map{png"my_image.png"} translate -(x+y)/2 scale 2 ] } } Input pigments should fall between <-1,-1,-infinity> and <1,1,infinity>. __________ | Examples | ŻŻŻŻŻŻŻŻŻŻ It probably seems more complicated than it really is :/ Check out these example scene files (posted in the p.t.scene-files RPI thread): RPI-basic.pov RPI-default.pov RPI-transforms.pov RPI-series.pov */ // RPI.inc /* the offset function... custom functions will also work but you may have to adjust the offsets in 'RPI_FunctionOffset' */ #ifndef(RPI_FCells) #declare RPI_FCells = function{ pattern{ cells translate(x+y+z)/2 warp{planar} } } #end // transform a pigment #macro RPI_PTransform(Pigment, TwistAmt, ScaleAmt, FadeAmt) #local Function = function{ pattern{ pigment_pattern{ Pigment } } } function{ Function( #if(TwistAmt=0) x #else (x*cos(z*2*pi*TwistAmt) - y*sin(z*2*pi*TwistAmt)) #end #if(ScaleAmt!=0) *(1+abs(RPI_FBands(z*64)-.5)*2*ScaleAmt) #end, #if(TwistAmt=0) y #else (x*sin(z*2*pi*TwistAmt) + y*cos(z*2*pi*TwistAmt)) #end #if(ScaleAmt!=0) *(1+abs(RPI_FBands(z*64)-.5)*2*ScaleAmt) #end, z ) #if(FadeAmt!=0) *(1-abs(RPI_FBands(z*480+(1+sqrt(5))/2 )-.5)*2*FadeAmt) #end } #end // A default pigment #declare RPI_DefaultPigment = pigment{ pigment_pattern{ cylindrical rotate x*90 } pigment_map{ [0 rgb 0] [1 spiral1 1 scale .75 scallop_wave pigment_map{ [0 rgb 0] [1 spiral1 8 scale .15 scallop_wave color_map{ [0 rgb .75] [1 rgb 1] } ] } ] } } // a ramp wave function #declare RPI_FBands = function(Dir){ select( -Dir, mod(Dir,1), 1-mod(-Dir,1) ) } // core function macro - it will be called 9 times in RPI() #macro RPI_FunctionOffset(xo, yo) RPI_Func( (RPI_FBands(x+.5)-1+xo+RPI_FCells(x-xo-4,y-yo+11,0)), (RPI_FBands(y+.5)-1+yo+RPI_FCells(x-xo+13,y-yo-27,0)), (z+RPI_FCells(x-xo+13,y-yo+59,0)) ) #end // main macro for generating the pattern #macro RPI(Pigment) // pigment->function conversion #local RPI_Func = function{ pattern{pigment_pattern{Pigment}} } // This, mostly, is the reason why it's so slow. function{ max( RPI_FunctionOffset(0, 0), RPI_FunctionOffset(-1, 0), RPI_FunctionOffset(1, 0), RPI_FunctionOffset(0, -1), RPI_FunctionOffset(0, 1), RPI_FunctionOffset(-1,-1), RPI_FunctionOffset(1, -1), RPI_FunctionOffset(-1, 1), RPI_FunctionOffset(1, 1) ) } #end // combines a series of PNG images into one gradient z pattern #macro RPI_CompileImages(ImageBaseName, NImages) // calculate zeros for the image name #local ZeroPadding = log(NImages)/log(10) + 1; pigment_pattern{ gradient z pigment_map{ #local V=0; #while(V