Main Docs Examples Download Gallery

Documentation

Functions

	CImplicitAutoCorrect           CRGBABlend
	CImplicitBasisFunction         CRGBABlendOps
	CImplicitBias                  CRGBAConstant
	CImplicitBlend                 CRGBACompositeChannels
	CImplicitBrightContrast        CRGBAHSVToRGBA
	CImplicitCache                 CRGBAImplicitGrayscale
	CImplicitCellular              CRGBARGBAToHSV
	CImplicitClamp                 CRGBARotateColor
	CImplicitCombiner              CRGBASelect
	CImplicitConstant
	CImplicitCos
	CImplicitExtractRGBAChannel
	CImplicitFractal
	CImplicitGain
	CImplicitGradient
	CImplicitRotateDomain
	CImplicitScaleDomain
	CImplicitScaleOffset
	CImplicitSelect
	CImplicitSin
	CImplicitSphere
	CImplicitTranslateDomain
					

Utilities

   
					

Basic Concepts

The basic idea of ANL is that functions are modular and may be connected together in chains to build more complex functions. All functions provide an interface allowing the function to be queried for a value. The interface provides methods for generating values in 2, 3, 4 or 6 dimensions. (The reason for providing such high orders of function is explained in the section on seamless noise.) Some modules are only generators, with no modifiable inputs or parameters, and are only connectable to other modules by being used as sources. Others are modifiers that somehow modify the output of another function; for these, other functions can be specified for the inputs.

The functions in ANL are organized into 2 main categories: Implicit functions and RGBA functions. Implicit functions are the noise functions that generate double-precision floating point output values. RGBA functions operate in RGBA space, and the values they output are 4-component single-precision floating point vectors representing RGBA colors. There are adapter functions that can take a number of Implicit functions and compose them into an RGBA function. As well, there is an adapter that can decompose an RGBA function, extracting a specified channel to be used as an Implicit source.

Because nothing is better than a working example to show how it works, here is a quick C++ program:

#include "anl.h"
   
int main()
{
    anl::CMWC4096 rnd;
    rnd.setSeedTime();
    anl::CImplicitFractal frac1(anl::FBM, anl::GRADIENT, anl::QUINTIC);
    anl::CImplicitFractal frac2(anl::FBM, anl::GRADIENT, anl::QUINTIC);
    anl::CImplicitFractal frac3(anl::FBM, anl::GRADIENT, anl::QUINTIC);
    anl::CImplicitFractal frac4(anl::RIDGEDMULTI, anl::GRADIENT, anl::QUINTIC);
    anl::CImplicitFractal frac5(anl::FBM, anl::GRADIENT, anl::QUINTIC);
    anl::CImplicitFractal frac6(anl::FBM, anl::GRADIENT, anl::QUINTIC);
    anl::CImplicitFractal frac7(anl::FBM, anl::GRADIENT, anl::QUINTIC);

    frac1.setSeed(rnd.get());
    frac2.setSeed(rnd.get());
    frac3.setSeed(rnd.get());
    frac4.setSeed(rnd.get());
    frac5.setSeed(rnd.get());
    frac6.setSeed(rnd.get());
    frac7.setSeed(rnd.get());


    anl::CImplicitAutoCorrect ac1(0.0, 1.0), ac2(0.0,1.0), ac3(0,1.0),
		ac4(0.0, 360.0), ac5(-1.0,1.0), ac6(-1.0,1.0), ac7(-1.0,1.0);
    ac1.setSource(&frac1);
    ac2.setSource(&frac2);
    ac3.setSource(&frac3);
    ac4.setSource(&frac4);
    ac5.setSource(&frac5);
    ac6.setSource(&frac6);
    ac7.setSource(&frac7);

    anl::CRGBACompositeChannels compose1(anl::RGB);

    compose1.setRedSource(&ac1);
    compose1.setGreenSource(&ac2);
    compose1.setBlueSource(&ac3);
    compose1.setAlphaSource(1.0);


    anl::CRGBARotateColor rot;
    rot.setAngle(&ac4);
    rot.setAxisX(&ac5);
    rot.setAxisY(&ac6);
    rot.setAxisZ(&ac7);
    rot.setNormalizeAxis(true);
    rot.setSource(&compose1);
	
   TArray2D img(256,256);

   anl::SMappingRanges ranges; 
   mapRGBA2D(anl::SEAMLESS_NONE,img,rot,ranges,0);
   saveRGBAArray((char*)"a.tga",&img);
   mapRGBA2D(anl::SEAMLESS_NONE,img,compose1,ranges,0);
   saveRGBAArray((char*)"b.tga",&img);

}
						

This example is kind of a neat one (if a trifle useless). The first thing the example does is to create a random number generator(RNG). ANL provides a number of different RNGs encapsulated in classes, and based on variants of RNGs devised by George Marsaglia. It seeds the generator using the system time. After that, 7 noise fractal modules are created. Many applications won't require nearly so many, and the fewer you can use the better your performance will be. After the fractals are generated, they are seeded from the RNG then 7 more modules of type AutoCorrect are created.

AutoCorrect modules attempt to "tame" the output of a function and remap it to a different range. Some functions (mult-fractals especially) are difficult to correct into an optimal range, and so AutoCorrect provides a way of doing it manually. When a function is set as the source to AutoCorrect, the module will iterate some number of times, and generate that many samples from random locations in the input source. It will determine the max and min values in the sample set, and from those will determine a scale/translate pair that is used to correct the output of the function into a desired range. The system isn't perfect, as the random sampling might still miss the absolute max and min values of the function, but it works sufficiently well. There is a bit of overhead in creating the function, during the calculate() phase when a source is initially set.

The AutoCorrect modules are set to specific ranges. The first three correct their inputs to the range (0,1). These will be used later to specify the Red, Green and Blue channels of an RGBA color. The next AutoCorrect remaps its input to the range (0,360). This is used to specify a randomized rotation angle, in degrees. The final three remap their inputs to the range (-1,1). These will be used to define a 3D rotation axis in RGBA color space.

Once the AutoCorrect modules are constructed, their sources are set from the fractals created earlier. Now, when the get() methods of the AutoCorrect modules are called, they will first call their respective source module for a value, then apply their scale/translate pairs to "fix" the value before returning it.

The next function created is an RGBA function, CompositeChannels. This function accepts up to 4 inputs from Implicit modules, one each for the channels of Red, Green, Blue and Alpha. (Or Hue, Saturation, Value and Alpha, if the function is operating in HSV space, settable via the mode parameter in the constructor.) This function represents how input parameters to functions work. If a function takes an Implicit input, the input may be over-ridden to a constant double-precision value, or it may be set to the output of another Implicit function. For example, in the above sample it would have been just as valid to specify the inputs to the CompositeChannels function as:

compose1.setRedSource(1.0);
compose1.setGreenSource(0.0);
compose1.setBlueSource(1.0);
compose1.setAlphaSource(1.0);
   
						

In this case, the output of the function would have been a constant value (magenta). Any combination of constants and functional inputs may be used. In our case, we are using functions for the Red, Green and Blue channels, and a constant value of 1.0 for Alpha. Now, if we map a 2D cross-section of this function as-is, and dump it to an image file, we'll get something like this:

Now, next we create an RGBA module of type RotateColor. This function takes an RGBA input, and 4 Implicit inputs. The Implicit inputs represent the (ax,ay,az,angle) components of an axis/angle rotation. The quantity being rotated is the RGBA color, in colorspace. Each color channel is first re-mapped to (-1,1), then a matrix is contructed from the axis/angle rotation. The components are transformed by this matrix, then re-normalized to (0,1) and output. For the inputs, we set our ComposeChannels function as the RGBA input, and our remaining 4 fractal modules for the (ax,ay,az,angle) inputs. Again, as before, it is just as easy to use double-precision constants for these inputs, and it is also as easy to specify an RGBA constant for the RGBA input, rather than the compose function.

Following that, we create a 2D RGBA buffer (see utilities for more information) then map a region of it and save it as a TGA file. The result looks something like this:

Some other examples produced after tinkering with the re-mappings in AutoCorrect and some of the other parameters:

To recap, we compose an RGBA from 3 channels of fractal noise, then rotate the color around an axis represented by 3 more channels of fractal noise, rotating by an angle specified by a final channel of fractal noise. The results are pretty, but also pretty useless. However, it does demonstrate the basic idea of the library. More practical examples are available in the examples section.

Implicit Modules

Implicit modules output double-precision float values. Implicit functions are derived from CImplicitModuleBase:

	class CImplicitModuleBase
	{
		public:
		virtual void setSeed(unsigned int seed);

		virtual double get(double x, double y)=0;
		virtual double get(double x, double y, double z)=0;
		virtual double get(double x, double y, double z, double w)=0;
		virtual double get(double x, double y, double z, double w, double u, double v)=0;
	};
						

Noise values are obtained by calling one of the get() methods provided, with the appropriate number of coordinates. Note that the performance of the system as a hold is affected by the dimensionality of the function called, so a 6D function will take significantly longer than a 2D function. Typical applications will probably stick with 2D or 3D versions; the higher orders are provided for the purpose of seamless mapping.

RGBA

RGBA modules operate int he RGBA colorspace, and are useful for creating color map, ie for textures. They typically operate by extracting data from relevant Implicit sources, and converting that data to color information somehow. All RGBA functions are derived from CRGBAModuleBase:

	class CRGBAModuleBase
    {
        public:
        CRGBAModuleBase(){}
        virtual ~CRGBAModuleBase(){}

        void setSeed(unsigned int){};

        virtual SRGBA get(double x, double y)=0;
        virtual SRGBA get(double x, double y, double z)=0;
        virtual SRGBA get(double x, double y, double z, double w)=0;
        virtual SRGBA get(double x, double y, double z, double w, double u, double v)=0;
    };
					

RGBA modules return a value of type SRGBA:

   struct SRGBA
    {
        SRGBA();
        SRGBA(float r, float g, float b, float a);
        SRGBA(float v);
		
        float rgba[4];
    };
					

The typical value range for the components of an SRGBA are (0,1). Typically, these values will map to (0,255) in unsigned char RGB colorspace, and anything beyond them is clamped. However, how an SRGBA is actually converted to a color is really up to the application.

Utilities

ANL provides a number of systems for the purpose of convenience.

All content on page copyright 2011 Joshua Tippetts