/* * More pattern ideas. */ #include "frame.h" #include "vector.h" #include "povproto.h" #include "matrices.h" #include "pattern.h" #include "povray.h" #include "texture.h" #include "image.h" #include "txttest.h" #include "colour.h" /***************************************************************************** * Static functions ******************************************************************************/ static DBL blotches (VECTOR EPoint); static DBL cells (VECTOR EPoint); static DBL bands (VECTOR EPoint, TPATTERN *TPat); static DBL sheet (VECTOR EPoint, TPATTERN *TPat); /***************************************************************************** * * FUNCTION * * blotches * * INPUT * * EPoint -- The point in 3d space at which the pattern * is evaluated. * OUTPUT * * RETURNS * * DBL value in the range 0.0 to 1.0 * * AUTHOR * * John VanSickle, based on code by Jim McElhiney * * DESCRIPTION * * "blotches": * * New colour function by John VanSickle, * vansickl@erols.com * * Assigns a pseudorandom point to each unit cube, and another float from 0 to * 1 to each cube. The nearest pseudorandom point to the evaluated point is * selected, and its associated pseudorandom value is returned. It creates * regions of uniform value. * * All "blotches" specific source code and examples are in the public domain. * * CHANGES * Oct 1994 : original crackle code adapted by [CY] * Jul 1999 : adapted for a different pattern by [JV] * ******************************************************************************/ static DBL blotches (VECTOR EPoint) { int i,j,temp,seed; long thisseed; DBL sum, minsum, minsum2, tf; VECTOR sv, tv, dv, t1, add; static int bvc; static long lastbeed = 0x80000000; static VECTOR bv[81]; Assign_Vector(tv,EPoint); /* * Check to see if the input point is in the same unit cube as the last * call to this function, to use cache of cubelets for speed. */ thisseed = PickInCube(tv, t1); if (thisseed != lastbeed) { /* * No, not same unit cube. Calculate the random points for this new * cube and its 80 neighbours which differ in any axis by 1 or 2. * Why distance of 2? If there is 1 point in each cube, located * randomly, it is possible for the closest random point to be in the * cube 2 over, or the one two over and one up. It is NOT possible * for it to be two over and two up. Picture a 3x3x3 cube with 9 more * cubes glued onto each face. */ /* Now store a points for this cube and each of the 80 neighbour cubes. */ bvc = 0; for (add[X] = -2.0; add[X] < 2.5; add[X] +=1.0) { for (add[Y] = -2.0; add[Y] < 2.5; add[Y] += 1.0) { for (add[Z] = -2.0; add[Z] < 2.5; add[Z] += 1.0) { /* For each cubelet in a 5x5 cube. */ if ((fabs(add[X])>1.5)+(fabs(add[Y])>1.5)+(fabs(add[Z])>1.5) <= 1.0) { /* Yes, it's within a 3d knight move away. */ VAdd(sv, tv, add); PickInCube(sv, t1); bv[bvc][X] = t1[X]; bv[bvc][Y] = t1[Y]; bv[bvc][Z] = t1[Z]; bvc++; } } } } lastbeed = thisseed; } /* * Find the point with the shortest distance from the input point. * Loop invariant: minsum is shortest dist */ VSub(dv, bv[0], tv); minsum = VSumSqr(dv); j=0; /* Loop for the 81 cubelets to find closest. */ for (i = 1; i < bvc; i++) { VSub(dv, bv[i], tv); sum = VSumSqr(dv); if (sum < minsum) { minsum = sum; j=i; } } /* select a random value based on the cube from which this came. */ seed = Hash3d((int)bv[j][X], (int)bv[j][Y], (int)bv[j][Z]); temp = POV_GET_OLD_RAND(); /* save current seed */ POV_SRAND(seed); /* The first three values were used for the random point, and shouldn't be used for the value of the region */ FRAND(); FRAND(); FRAND(); tf = FRAND(); POV_SRAND(temp); /* restore */ return min(tf); } /***************************************************************************** * * FUNCTION * * blotches * * INPUT * * EPoint -- The point in 3d space at which the pattern * is evaluated. * OUTPUT * * RETURNS * * DBL value in the range 0.0 to 1.0 * * AUTHOR * * John VanSickle * * DESCRIPTION * * "cells": * * New colour function by John VanSickle, * vansickl@erols.com * * Assigns a pseudorandom value to each unit cube. The value for the cube in * which the evaluted point lies is returned. * * All "cells" specific source code and examples are in the public domain. * * CHANGES * Oct 1994 : original crackle code adapted by [CY] * Jul 1999 : adapted for a different pattern by [JV] * ******************************************************************************/ static DBL cells (VECTOR EPoint) { int temp,seed; DBL tf; /* select a random value based on the cube from which this came. */ seed = Hash3d((int)EPoint[X], (int)EPoint[Y], (int)EPoint[Z]); temp = POV_GET_OLD_RAND(); /* save current seed */ POV_SRAND(seed); tf = FRAND(); POV_SRAND(temp); /* restore */ return min(tf); } /***************************************************************************** * * FUNCTION * * bands * * INPUT * * EPoint -- The point in 3d space at which the pattern * is evaluated. * * OUTPUT * * RETURNS * * DBL value in the range 0.0 to 1.0 * * AUTHOR * * John VanSickle, based on the gradient code * * DESCRIPTION * * banded Pattern - just like gradient, but is not mirrored around the origin, * and the bands are of uniform width, regardless of the direction of the * vector. * * CHANGES * Oct 1994 : adapted from pigment by [CY] * Jul 1999 : adapted from gradient by [JV] * ******************************************************************************/ /* ¡MUY IMPORTANTE! This function expects the Vals.Gradient vector in TPat to * be normalized (ie, unit length). If the vector is greater or less than * unit length, there will be a scaling effect on the pattern. I could have * divided by the magnitude of the vector, but since this function will be * called more than once by the renderer, it is more appropriate for the * parser to normalize the vector (where it need be done only once). */ static DBL banded (VECTOR EPoint, TPATTERN *TPat) { register DBL value; value = EPoint[X]*TPat->Vals.Gradient[X] + EPoint[Y]*TPat->Vals.Gradient[Y]+EPoint[Z]*TPat->Vals.Gradient[Z]; return(value-floor(value)); } /***************************************************************************** * * FUNCTION * * sheet * * INPUT * * EPoint -- The point in 3d space at which the pattern * is evaluated. * * OUTPUT * * RETURNS * * DBL value in the range 0.0 to 1.0 * * AUTHOR * * John VanSickle, based on the gradient code * * DESCRIPTION * * Takes the dot product of the evaluated point and a specified vector. * If the product is <0, 0 is returned. If the product is >1, 1 is returned. * Otherwise the product is returned. This is basically a non-repeating, * non-mirrored gradient, but like the banded pattern above, the width of * the band is independent of direction of the vector. * * CHANGES * Oct 1994 : adapted from pigment by [CY] * Jul 1999 : adapted from gradient by [JV] * ******************************************************************************/ /* ¡MUY IMPORTANTE! This function expects the Vals.Gradient vector in TPat to * be normalized (ie, unit length). If the vector is greater or less than * unit length, there will be a scaling effect on the pattern. I could have * divided by the magnitude of the vector, but since this function will be * called more than once by the renderer, it is more appropriate for the * parser to normalize the vector (where it need be done only once). */ static DBL sheet (VECTOR EPoint, TPATTERN *TPat) { register DBL value; value = EPoint[X]*TPat->Vals.Gradient[X] + EPoint[Y]*TPat->Vals.Gradient[Y]+EPoint[Z]*TPat->Vals.Gradient[Z]; return(value>1.0 ? 1.0 : (value<0.0? 0.0:value)); }