|
 |
One of the things that I have sustained an active interest in over the past
several years is the creation of procedural patterns.
Doing this in SDL to create pigment {function {}} patterns can be challenging
due to the scalar-only nature of the function parser / virtual machine.
During experimentation with infinitely tiling a plane or filling space, it
became readily apparent that the stock modulo function - mod (N, M) - did not
remain consistent across the -value|0|+value transition.
So I crafted my own. And then another. And then another.
So which one was "right"? Apparently this is one of those situation-dependent
functions like pow (0, 0).
So I did some investigating and there are a number of different ways to perform
modular arithmetic so that the result has the specific characteristics that you
need in your given situation. And here's an important note: you may need to use
different behaviours in different parts of your equations.
I discovered that my custom-rolled fmod () function usually worked for what I
needed, but when applied in a blanket manner was inappropriate for certain parts
of my patterns. So I use fmod () some places, and stock mod () in others.
Here's a small starting library. I'm sure there are more variations.
// MODULO_LIB.inc
// Behavioral Modulo Library for POV-Ray SDL
// Guarded, scalar-only, function-safe
#ifndef (MODULO_LIB_INC)
#declare MODULO_LIB_INC = yes;
// --- HARD MODULO ---
#declare MOD_HARD_BASIC = function (V, P) { mod(V, P) };
// --- ABSOLUTE MODULO ---
#declare MOD_ABS_BASIC = function (V, P) { mod(abs(V), P) };
// --- PHASE-CORRECTED ABS MODULO ---
#declare MOD_ABS_PHASE = function (V, P)
{ select(V, 1 - mod(abs(V), P), mod(abs(V), P)) };
// --- CENTERED MODULO ---
#declare MOD_CENTER_BASIC = function (V, P)
{ mod(V + P/2, P) - P/2 };
// --- TRIANGLE MODULO ---
#declare MOD_TRI_BASIC = function (V, P)
{ abs(mod(V, 2*P) - P) };
// --- SMOOTH MODULO ---
#declare MOD_SMOOTH_BASIC = function (V, P)
{ P * (0.5 - 0.5*cos(2*pi*V/P)) };
#declare MOD_SMOOTH_SIGNED = function (V, P)
{ V - P * sin(2*pi*V/P)/(2*pi) };
// --- NESTED MODULO ---
#declare MOD_NEST_BASIC = function (V, A, B)
{ mod(mod(V, A), B) };
#declare MOD_NEST_ABS = function (V, A, B)
{ mod(mod(abs(V), A), B) };
#declare MOD_NEST_PHASE = function (V, A, B)
{ select(V, B - mod(mod(abs(V), A), B), mod(mod(abs(V), A), B)) };
// --- LOGIC MODULO ---
#declare MOD_LOGIC_PARITY = function (V, P)
{ mod(floor(abs(V)/P), 2) };
#declare MOD_LOGIC_QUANTIZED = function (V, P, S)
//{ round(mod(V, P)/S)*S };
{ int(mod(V, P)/S)*S };
// --- WINDOWED / CLAMPED ---
#declare MOD_LOGIC_WINDOW = function (V, P)
{ select(V, mod(abs(V), P), 0) };
#declare MOD_LOGIC_CLAMP = function (V, P, C)
{ min(mod(V, P), C) };
// --- METRIC HELPERS ---
#declare MOD_METRIC_RADIAL = function (R, P)
{ mod(R, P) };
#declare MOD_METRIC_ANGLE = function (A, P)
{ mod(A, P) };
#end
// *** end of file ***
Post a reply to this message
Attachments:
Download 'modulo_lib_full_demo.png' (53 KB)
Preview of image 'modulo_lib_full_demo.png'

|
 |