fractorium/Source/Ember/Variation.h
Person c3078f018a --User changes
-Update various tooltips.
 -Increase precision of affine and xaos spinners.
 -Increase precision of fields written in Xml files to 8.

--Bug fixes
 -When rendering on the CPU, if the number of threads didn't divide evenly into the number of rows, it would leave a blank spot on the last few rows.
 -Fix numerous parsing bugs when reading .chaos files.
 -Added compatibility fixes and/or optimizations to the following variations: asteria, bcircle, bcollide, bipolar, blob2, btransform, cell, circlecrop, circlecrop2, collideoscope, cpow2, cropn, cross, curl, depth_ngon2, depth_sine2, edisc, eRotate, escher, fan2, hex_rand, hypershift, hypershift2, hypertile1, julia, julian, julian2, juliaq, juliascope, lazyjess, log, loonie2, murl, murl2, npolar, oscilloscope2, perspective, phoenix_julia, sphericaln, squish, starblur, starblur2, truchet, truchet_glyph, waffle, wavesn.
2023-11-29 15:47:31 -07:00

2639 lines
68 KiB
C++

#pragma once
#include "Point.h"
#include "Isaac.h"
#include "VarFuncs.h"
/// <summary>
/// Base variation classes. Individual variations will be grouped into files of roughly 50
/// to avoid a single file becoming too unweildy.
/// </summary>
namespace EmberNs
{
/// <summary>
/// Xform and Variation need each other, but each can't include the other.
/// So Xform includes this file, and use a forward declaration here.
/// </summary>
template <typename T> class Xform;
/// <summary>
/// The type of variation: regular, pre or post.
/// </summary>
enum class eVariationType : et
{
VARTYPE_REG,
VARTYPE_PRE,
VARTYPE_POST,
};
/// <summary>
/// How to handle the results of the variation when it's a pre or post.
/// If the calculation involved the input points, then it should be directly assigned
/// to the output. However, if they did not involve the input points, they should be added
/// to the output.
/// </summary>
enum class eVariationAssignType : et
{
ASSIGNTYPE_SET,
ASSIGNTYPE_SUM
};
#define WEIGHT_PREFIX "parVars[WEIGHT_"
/// <summary>
/// Complete list of every variation class ID.
/// </summary>
enum class eVariationId : glm::uint
{
VAR_ARCH,
VAR_ARCSECH,
VAR_ARCSECH2,
VAR_ARCSINH,
VAR_ARCTANH,
VAR_ASTERIA,
VAR_AUGER ,
VAR_BARYCENTROID,
VAR_BCIRCLE ,
VAR_BCOLLIDE ,
VAR_BENT ,
VAR_BENT2 ,
VAR_BIPOLAR ,
VAR_BISPLIT ,
VAR_BLADE ,
VAR_BLADE3D ,
VAR_BLOB ,
VAR_BLOB2 ,
VAR_BLOB3D ,
VAR_BLOCK ,
VAR_BLOCKY ,
VAR_BLUR ,
VAR_BLUR_CIRCLE ,
VAR_BLUR_HEART,
VAR_BLUR_LINEAR ,
VAR_BLUR_PIXELIZE,
VAR_BLUR_SQUARE ,
VAR_BLUR_ZOOM ,
VAR_BLUR3D ,
VAR_BMOD ,
VAR_BOARDERS ,
VAR_BOARDERS2 ,
VAR_BSWIRL ,
VAR_BTRANSFORM ,
VAR_BUBBLE ,
VAR_BUBBLE2 ,
VAR_BUBBLET3D ,
VAR_BUTTERFLY ,
VAR_BWRAPS ,
VAR_BWRAPS_RAND ,
VAR_CARDIOID ,
VAR_CELL ,
VAR_CHECKS ,
VAR_CIRCLEBLUR ,
VAR_CIRCLECROP,
VAR_CIRCLECROP2,
VAR_CIRCLELINEAR,
VAR_CIRCLERAND,
VAR_CIRCLESPLIT,
VAR_CIRCLETRANS1,
VAR_CIRCLE_RAND,
VAR_CIRCLIZE ,
VAR_CIRCLIZE2 ,
VAR_CIRCUS,
VAR_COLLIDEOSCOPE,
VAR_CONCENTRIC ,
VAR_CONIC ,
VAR_COS ,
VAR_COS_WRAP ,
VAR_COSH ,
VAR_COSHQ,
VAR_COSINE ,
VAR_COSQ,
VAR_COT ,
VAR_COTH ,
VAR_COTH_SPIRAL,
VAR_COTHQ ,
VAR_COTQ ,
VAR_CPOW ,
VAR_CPOW2 ,
VAR_CPOW3 ,
VAR_CRACKLE ,
VAR_CRACKLE2 ,
VAR_CRESCENTS ,
VAR_CROB ,
VAR_CROP ,
VAR_CROPN ,
VAR_CROSS ,
VAR_CSC ,
VAR_CSCH ,
VAR_CSCHQ ,
VAR_CSCQ ,
VAR_CUBIC3D ,
VAR_CUBIC_LATTICE3D,
VAR_CURL ,
VAR_CURL3D ,
VAR_CURL_SP,
VAR_CURVATURE,
VAR_CURVE ,
VAR_CYLINDER ,
VAR_CYLINDER2,
VAR_DELTA_A ,
VAR_DEPTH,
VAR_DEPTH_BLUR,
VAR_DEPTH_BLUR2,
VAR_DEPTH_GAUSSIAN,
VAR_DEPTH_GAUSSIAN2,
VAR_DEPTH_NGON,
VAR_DEPTH_NGON2,
VAR_DEPTH_SINE,
VAR_DEPTH_SINE2,
VAR_DIAMOND ,
VAR_DISC ,
VAR_DISC2 ,
VAR_DISC3D ,
VAR_DRAGONFIRE,
VAR_DUST ,
VAR_D_SPHERICAL ,
VAR_ECLIPSE ,
VAR_ECOLLIDE ,
VAR_EDISC ,
VAR_EJULIA ,
VAR_ELLIPTIC ,
VAR_EMOD ,
VAR_EMOTION ,
VAR_ENNEPERS ,
VAR_EPISPIRAL ,
VAR_EPUSH ,
VAR_ERF ,
VAR_EROTATE ,
VAR_ESCALE ,
VAR_ESCHER ,
VAR_ESTIQ,
VAR_ESWIRL ,
VAR_EX ,
VAR_EXCINIS ,
VAR_EXP ,
VAR_EXP2 ,
VAR_EXPO ,
VAR_EXPONENTIAL ,
VAR_EXTRUDE ,
VAR_EYEFISH ,
VAR_FALLOFF ,
VAR_FALLOFF2 ,
VAR_FALLOFF3 ,
VAR_FAN ,
VAR_FAN2 ,
VAR_FARBLUR,
VAR_FDISC ,
VAR_FIBONACCI ,
VAR_FIBONACCI2 ,
VAR_FISHEYE ,
VAR_FLATTEN ,
VAR_FLIP_CIRCLE ,
VAR_FLIP_X ,
VAR_FLIP_Y ,
VAR_FLOWER ,
VAR_FLOWER_DB ,
VAR_FLUX ,
VAR_FOCI ,
VAR_FOCI3D ,
VAR_FOCI_P ,
VAR_FOURTH,
VAR_FUNNEL ,
VAR_GAMMA ,
VAR_GAUSSIAN,
VAR_GAUSSIAN_BLUR,
VAR_GDOFFS,
VAR_GLYNNIA ,
VAR_GLYNNIA2 ,
VAR_GLYNNSIM1 ,
VAR_GLYNNSIM2 ,
VAR_GLYNNSIM3 ,
VAR_GLYNNSIM4 ,
VAR_GLYNNSIM5 ,
VAR_GNARLY,
VAR_GRIDOUT ,
VAR_HANDKERCHIEF,
VAR_HEART ,
VAR_HEAT,
VAR_HELICOID,
VAR_HELIX,
VAR_HEMISPHERE ,
VAR_HENON ,
VAR_HEXAPLAY3D ,
VAR_HEXCROP ,
VAR_HEXES ,
VAR_HEXNIX3D ,
VAR_HEX_MODULUS,
VAR_HEX_RAND,
VAR_HEX_TRUCHET,
VAR_HO ,
VAR_HOLE ,
VAR_HORSESHOE ,
VAR_HYPERBOLIC ,
VAR_HYPERCROP ,
VAR_HYPERSHIFT ,
VAR_HYPERSHIFT2 ,
VAR_HYPERTILE ,
VAR_HYPERTILE1 ,
VAR_HYPERTILE2 ,
VAR_HYPERTILE3D ,
VAR_HYPERTILE3D1,
VAR_HYPERTILE3D2,
VAR_IDISC ,
VAR_INKDROP,
VAR_INTERFERENCE2,
VAR_JAC_CN ,
VAR_JAC_DN ,
VAR_JAC_SN ,
VAR_JULIA ,
VAR_JULIA3D ,
VAR_JULIA3DQ ,
VAR_JULIA3DZ ,
VAR_JULIAC,
VAR_JULIAN ,
VAR_JULIAN2 ,
VAR_JULIAN3DX,
VAR_JULIANAB,
VAR_JULIAQ ,
VAR_JULIASCOPE ,
VAR_KALEIDOSCOPE,
VAR_LAZYJESS ,
VAR_LAZYSUSAN ,
VAR_LAZY_TRAVIS ,
VAR_LENS ,
VAR_LINE ,
VAR_LINEAR ,
VAR_LINEAR_T ,
VAR_LINEAR_T3D ,
//VAR_LINEAR_XZ ,
//VAR_LINEAR_YZ ,
VAR_LINEAR3D ,
VAR_LISSAJOUS ,
VAR_LOG ,
VAR_LOG_DB ,
VAR_LOQ ,
VAR_LOONIE ,
VAR_LOONIE2 ,
VAR_LOONIE3 ,
VAR_LOONIE3D ,
VAR_LOZI ,
VAR_MASK ,
VAR_MCARPET ,
VAR_MIRROR_X,
VAR_MIRROR_Y,
VAR_MIRROR_Z,
VAR_MOBIQ,
VAR_MOBIUS ,
VAR_MOBIUS_STRIP,
VAR_MOBIUSN ,
VAR_MODULUS ,
VAR_MODULUSX ,
VAR_MODULUSY ,
VAR_MURL ,
VAR_MURL2 ,
VAR_NBLUR ,
VAR_NGON ,
VAR_NOISE ,
VAR_NPOLAR ,
VAR_OCTAGON ,
VAR_OCTAPOL ,
VAR_ORTHO ,
VAR_OSCILLOSCOPE,
VAR_OSCILLOSCOPE2,
VAR_OVOID ,
VAR_OVOID3D ,
VAR_PANORAMA1 ,
VAR_PANORAMA2 ,
VAR_PARABOLA ,
VAR_PDJ ,
VAR_PERSPECTIVE ,
VAR_PETAL ,
VAR_PHOENIX_JULIA,
VAR_PIE ,
VAR_PIE3D ,
VAR_PIXEL_FLOW ,
VAR_POINCARE ,
VAR_POINCARE2 ,
VAR_POINCARE3D ,
VAR_POINT_SYMMETRY,
VAR_POLAR ,
VAR_POLAR2 ,
VAR_POLYNOMIAL ,
VAR_POPCORN ,
VAR_POPCORN2 ,
VAR_POPCORN23D ,
VAR_POW_BLOCK ,
VAR_POWER ,
VAR_PRESSURE_WAVE,
VAR_PROJECTIVE ,
VAR_PROSE3D ,
VAR_PSPHERE ,
VAR_PULSE ,
VAR_Q_ODE,
VAR_RADIAL_BLUR ,
//VAR_RADIAL_GAUSSIAN,
VAR_RAND_CUBES ,
VAR_RATIONAL3 ,
VAR_RAYS ,
VAR_RAYS1 ,
VAR_RAYS2 ,
VAR_RAYS3 ,
VAR_RBLUR,
VAR_RECTANGLES ,
VAR_RINGS ,
VAR_RINGS2 ,
VAR_RIPPLE ,
VAR_RIPPLED ,
VAR_ROTATE,
VAR_ROTATE_X,
VAR_ROTATE_Y,
VAR_ROTATE_Z,
VAR_ROUNDSPHER ,
VAR_ROUNDSPHER3D,
VAR_SCRY ,
VAR_SCRY2 ,
VAR_SCRY3D ,
VAR_SEC ,
VAR_SECANT2 ,
VAR_SECH ,
VAR_SECHQ,
VAR_SECQ,
VAR_SEPARATION ,
VAR_SHIFT ,
VAR_SHRED_RAD ,
VAR_SHRED_LIN ,
VAR_SIGMOID ,
VAR_SIN ,
VAR_SINEBLUR ,
VAR_SINH ,
VAR_SINHQ ,
VAR_SINQ ,
VAR_SINTRANGE,
VAR_SINUS_GRID ,
VAR_SINUSOIDAL ,
VAR_SINUSOIDAL3D,
VAR_SMARTSHAPE,
//VAR_SMARTCROP ,
VAR_SPHER ,
VAR_SPHEREBLUR ,
VAR_SPHERICAL ,
VAR_SPHERICAL3D ,
VAR_SPHERICALN ,
VAR_SPHERIVOID,
VAR_SPHYP3D ,
VAR_SPIRAL ,
VAR_SPIRAL_WING ,
VAR_SPIROGRAPH ,
VAR_SPLIT ,
VAR_SPLIT_BRDR,
VAR_SPLITS ,
VAR_SPLITS3D ,
VAR_SQUARE ,
VAR_SQUARES ,
VAR_SQUARE3D ,
VAR_SQUARIZE ,
VAR_SQUIRREL ,
VAR_SQUISH,
VAR_SSCHECKS ,
VAR_STARBLUR ,
VAR_STARBLUR2 ,
VAR_STRIPES ,
VAR_STWIN ,
VAR_SUPER_SHAPE ,
VAR_SUPER_SHAPE3D,
VAR_SVF ,
VAR_SWIRL ,
VAR_SWIRL3 ,
VAR_SWIRL3R ,
VAR_SYNTH ,
VAR_TAN ,
VAR_TANCOS,
VAR_TANGENT ,
VAR_TANH ,
VAR_TANHQ ,
VAR_TANH_SPIRAL ,
VAR_TANQ ,
VAR_TARGET ,
VAR_TARGET0 ,
VAR_TARGET2 ,
VAR_TAURUS ,
VAR_TILE_HLP,
VAR_TILE_LOG,
VAR_TRADE ,
VAR_TRUCHET,
VAR_TRUCHET_FILL,
VAR_TRUCHET_HEX_FILL,
VAR_TRUCHET_HEX_CROP,
VAR_TRUCHET_GLYPH,
VAR_TRUCHET_INV,
VAR_TRUCHET_KNOT,
VAR_TWINTRIAN ,
VAR_TWO_FACE ,
VAR_UNICORNGALOSHEN,
VAR_UNPOLAR ,
VAR_VIBRATION,
VAR_VIBRATION2,
VAR_VIGNETTE,
VAR_VORON,
VAR_W ,
VAR_WAFFLE,
VAR_WAVES ,
VAR_WAVES2 ,
VAR_WAVES22,
VAR_WAVES23,
VAR_WAVES23D ,
VAR_WAVES2B ,
VAR_WAVES2_RADIAL,
VAR_WAVES3,
VAR_WAVES4,
VAR_WAVES42,
VAR_WAVESN ,
VAR_WDISC ,
VAR_WEDGE ,
VAR_WEDGE_JULIA ,
VAR_WEDGE_SPH ,
VAR_WHORL ,
VAR_X ,
VAR_XERF ,
VAR_XHEART ,
VAR_XTRB ,
VAR_Y ,
VAR_Z ,
VAR_ZBLUR ,
VAR_ZCONE ,
VAR_ZSCALE ,
VAR_ZTRANSLATE,
VAR_PRE_ARCH,
VAR_PRE_ARCSECH,
VAR_PRE_ARCSECH2,
VAR_PRE_ARCSINH,
VAR_PRE_ARCTANH,
VAR_PRE_ASTERIA,
VAR_PRE_AUGER,
VAR_PRE_BARYCENTROID,
VAR_PRE_BCIRCLE,
VAR_PRE_BCOLLIDE,
VAR_PRE_BENT,
VAR_PRE_BENT2,
VAR_PRE_BIPOLAR,
VAR_PRE_BISPLIT,
VAR_PRE_BLADE,
VAR_PRE_BLADE3D,
VAR_PRE_BLOB,
VAR_PRE_BLOB2,
VAR_PRE_BLOB3D,
VAR_PRE_BLOCK,
VAR_PRE_BLOCKY,
VAR_PRE_BLUR,
VAR_PRE_BLUR_CIRCLE,
VAR_PRE_BLUR_HEART,
VAR_PRE_BLUR_LINEAR,
VAR_PRE_BLUR_PIXELIZE,
VAR_PRE_BLUR_SQUARE,
VAR_PRE_BLUR_ZOOM,
VAR_PRE_BLUR3D,
VAR_PRE_BMOD,
VAR_PRE_BOARDERS,
VAR_PRE_BOARDERS2,
VAR_PRE_BSWIRL,
VAR_PRE_BTRANSFORM,
VAR_PRE_BUBBLE,
VAR_PRE_BUBBLE2,
VAR_PRE_BUBBLET3D,
VAR_PRE_BUTTERFLY,
VAR_PRE_BWRAPS,
VAR_PRE_BWRAPS_RAND,
VAR_PRE_CARDIOID,
VAR_PRE_CELL,
VAR_PRE_CHECKS,
VAR_PRE_CIRCLEBLUR,
VAR_PRE_CIRCLECROP,
VAR_PRE_CIRCLECROP2,
VAR_PRE_CIRCLELINEAR,
VAR_PRE_CIRCLERAND,
VAR_PRE_CIRCLESPLIT,
VAR_PRE_CIRCLETRANS1,
VAR_PRE_CIRCLE_RAND,
VAR_PRE_CIRCLIZE,
VAR_PRE_CIRCLIZE2,
VAR_PRE_CIRCUS,
VAR_PRE_COLLIDEOSCOPE,
VAR_PRE_CONCENTRIC,
VAR_PRE_CONIC,
VAR_PRE_COS,
VAR_PRE_COS_WRAP,
VAR_PRE_COSH,
VAR_PRE_COSHQ,
VAR_PRE_COSINE,
VAR_PRE_COSQ,
VAR_PRE_COT,
VAR_PRE_COTH,
VAR_PRE_COTH_SPIRAL,
VAR_PRE_COTHQ,
VAR_PRE_COTQ,
VAR_PRE_CPOW,
VAR_PRE_CPOW2,
VAR_PRE_CPOW3,
VAR_PRE_CRACKLE,
VAR_PRE_CRACKLE2,
VAR_PRE_CRESCENTS,
VAR_PRE_CROB,
VAR_PRE_CROP,
VAR_PRE_CROPN,
VAR_PRE_CROSS,
VAR_PRE_CSC,
VAR_PRE_CSCH,
VAR_PRE_CSCHQ,
VAR_PRE_CSCQ,
VAR_PRE_CUBIC3D,
VAR_PRE_CUBIC_LATTICE3D,
VAR_PRE_CURL,
VAR_PRE_CURL3D,
VAR_PRE_CURL_SP,
VAR_PRE_CURVATURE,
VAR_PRE_CURVE,
VAR_PRE_CYLINDER,
VAR_PRE_CYLINDER2,
VAR_PRE_DELTA_A,
VAR_PRE_DEPTH,
VAR_PRE_DEPTH_BLUR,
VAR_PRE_DEPTH_BLUR2,
VAR_PRE_DEPTH_GAUSSIAN,
VAR_PRE_DEPTH_GAUSSIAN2,
VAR_PRE_DEPTH_NGON,
VAR_PRE_DEPTH_NGON2,
VAR_PRE_DEPTH_SINE,
VAR_PRE_DEPTH_SINE2,
VAR_PRE_DIAMOND,
VAR_PRE_DISC,
VAR_PRE_DISC2,
VAR_PRE_DISC3D,
VAR_PRE_DRAGONFIRE,
VAR_PRE_DUST,
VAR_PRE_D_SPHERICAL,
VAR_PRE_ECLIPSE,
VAR_PRE_ECOLLIDE,
VAR_PRE_EDISC,
VAR_PRE_EJULIA,
VAR_PRE_ELLIPTIC,
VAR_PRE_EMOD,
VAR_PRE_EMOTION,
VAR_PRE_ENNEPERS,
VAR_PRE_EPISPIRAL,
VAR_PRE_EPUSH,
VAR_PRE_ERF,
VAR_PRE_EROTATE,
VAR_PRE_ESCALE,
VAR_PRE_ESCHER,
VAR_PRE_ESTIQ,
VAR_PRE_ESWIRL,
VAR_PRE_EX,
VAR_PRE_EXCINIS,
VAR_PRE_EXP,
VAR_PRE_EXP2,
VAR_PRE_EXPO,
VAR_PRE_EXPONENTIAL,
VAR_PRE_EXTRUDE,
VAR_PRE_EYEFISH,
VAR_PRE_FALLOFF,
VAR_PRE_FALLOFF2,
VAR_PRE_FALLOFF3,
VAR_PRE_FAN,
VAR_PRE_FAN2,
VAR_PRE_FARBLUR,
VAR_PRE_FDISC,
VAR_PRE_FIBONACCI,
VAR_PRE_FIBONACCI2,
VAR_PRE_FISHEYE,
VAR_PRE_FLATTEN,
VAR_PRE_FLIP_CIRCLE,
VAR_PRE_FLIP_X,
VAR_PRE_FLIP_Y,
VAR_PRE_FLOWER,
VAR_PRE_FLOWER_DB,
VAR_PRE_FLUX,
VAR_PRE_FOCI,
VAR_PRE_FOCI3D,
VAR_PRE_FOCI_P,
VAR_PRE_FOURTH,
VAR_PRE_FUNNEL,
VAR_PRE_GAMMA,
VAR_PRE_GAUSSIAN,
VAR_PRE_GAUSSIAN_BLUR,
VAR_PRE_GDOFFS,
VAR_PRE_GLYNNIA,
VAR_PRE_GLYNNIA2,
VAR_PRE_GLYNNSIM1,
VAR_PRE_GLYNNSIM2,
VAR_PRE_GLYNNSIM3,
VAR_PRE_GLYNNSIM4,
VAR_PRE_GLYNNSIM5,
VAR_PRE_GNARLY,
VAR_PRE_GRIDOUT,
VAR_PRE_HANDKERCHIEF,
VAR_PRE_HEART,
VAR_PRE_HEAT,
VAR_PRE_HELICOID,
VAR_PRE_HELIX,
VAR_PRE_HEMISPHERE,
VAR_PRE_HENON,
VAR_PRE_HEXAPLAY3D,
VAR_PRE_HEXCROP,
VAR_PRE_HEXES,
VAR_PRE_HEXNIX3D,
VAR_PRE_HEX_MODULUS,
VAR_PRE_HEX_RAND,
VAR_PRE_HEX_TRUCHET,
VAR_PRE_HO,
VAR_PRE_HOLE,
VAR_PRE_HORSESHOE,
VAR_PRE_HYPERBOLIC,
VAR_PRE_HYPERCROP,
VAR_PRE_HYPERSHIFT,
VAR_PRE_HYPERSHIFT2,
VAR_PRE_HYPERTILE,
VAR_PRE_HYPERTILE1,
VAR_PRE_HYPERTILE2,
VAR_PRE_HYPERTILE3D,
VAR_PRE_HYPERTILE3D1,
VAR_PRE_HYPERTILE3D2,
VAR_PRE_IDISC,
VAR_PRE_INKDROP,
VAR_PRE_INTERFERENCE2,
VAR_PRE_JAC_CN,
VAR_PRE_JAC_DN,
VAR_PRE_JAC_SN,
VAR_PRE_JULIA,
VAR_PRE_JULIA3D,
VAR_PRE_JULIA3DQ,
VAR_PRE_JULIA3DZ,
VAR_PRE_JULIAC,
VAR_PRE_JULIAN,
VAR_PRE_JULIAN2,
VAR_PRE_JULIAN3DX,
VAR_PRE_JULIANAB,
VAR_PRE_JULIAQ,
VAR_PRE_JULIASCOPE,
VAR_PRE_KALEIDOSCOPE,
VAR_PRE_LAZYJESS,
VAR_PRE_LAZYSUSAN,
VAR_PRE_LAZY_TRAVIS,
VAR_PRE_LENS,
VAR_PRE_LINE,
VAR_PRE_LINEAR,
VAR_PRE_LINEAR_T,
VAR_PRE_LINEAR_T3D,
//eVariationId::VAR_PRE_LINEAR_XZ,
//eVariationId::VAR_PRE_LINEAR_YZ,
VAR_PRE_LINEAR3D,
VAR_PRE_LISSAJOUS,
VAR_PRE_LOG,
VAR_PRE_LOG_DB,
VAR_PRE_LOQ,
VAR_PRE_LOONIE,
VAR_PRE_LOONIE2,
VAR_PRE_LOONIE3,
VAR_PRE_LOONIE3D,
VAR_PRE_LOZI,
VAR_PRE_MASK,
VAR_PRE_MCARPET,
VAR_PRE_MIRROR_X,
VAR_PRE_MIRROR_Y,
VAR_PRE_MIRROR_Z,
VAR_PRE_MOBIQ,
VAR_PRE_MOBIUS,
VAR_PRE_MOBIUS_STRIP,
VAR_PRE_MOBIUSN,
VAR_PRE_MODULUS,
VAR_PRE_MODULUSX,
VAR_PRE_MODULUSY,
VAR_PRE_MURL,
VAR_PRE_MURL2,
VAR_PRE_NBLUR,
VAR_PRE_NGON,
VAR_PRE_NOISE,
VAR_PRE_NPOLAR,
VAR_PRE_OCTAGON,
VAR_PRE_OCTAPOL,
VAR_PRE_ORTHO,
VAR_PRE_OSCILLOSCOPE,
VAR_PRE_OSCILLOSCOPE2,
VAR_PRE_OVOID,
VAR_PRE_OVOID3D,
VAR_PRE_PANORAMA1,
VAR_PRE_PANORAMA2,
VAR_PRE_PARABOLA,
VAR_PRE_PDJ,
VAR_PRE_PERSPECTIVE,
VAR_PRE_PETAL,
VAR_PRE_PHOENIX_JULIA,
VAR_PRE_PIE,
VAR_PRE_PIE3D,
VAR_PRE_PIXEL_FLOW,
VAR_PRE_POINCARE,
VAR_PRE_POINCARE2,
VAR_PRE_POINCARE3D,
VAR_PRE_POINT_SYMMETRY,
VAR_PRE_POLAR,
VAR_PRE_POLAR2,
VAR_PRE_POLYNOMIAL,
VAR_PRE_POPCORN,
VAR_PRE_POPCORN2,
VAR_PRE_POPCORN23D,
VAR_PRE_POW_BLOCK,
VAR_PRE_POWER,
VAR_PRE_PRESSURE_WAVE,
VAR_PRE_PROJECTIVE,
VAR_PRE_PROSE3D,
VAR_PRE_PSPHERE,
VAR_PRE_PULSE,
VAR_PRE_Q_ODE,
VAR_PRE_RADIAL_BLUR,
VAR_PRE_RAND_CUBES,
VAR_PRE_RATIONAL3,
VAR_PRE_RAYS,
VAR_PRE_RAYS1,
VAR_PRE_RAYS2,
VAR_PRE_RAYS3,
VAR_PRE_RBLUR,
VAR_PRE_RECTANGLES,
VAR_PRE_RINGS,
VAR_PRE_RINGS2,
VAR_PRE_RIPPLE,
VAR_PRE_RIPPLED,
VAR_PRE_ROTATE,
VAR_PRE_ROTATE_X,
VAR_PRE_ROTATE_Y,
VAR_PRE_ROTATE_Z,
VAR_PRE_ROUNDSPHER,
VAR_PRE_ROUNDSPHER3D,
VAR_PRE_SCRY,
VAR_PRE_SCRY2,
VAR_PRE_SCRY3D,
VAR_PRE_SEC,
VAR_PRE_SECANT2,
VAR_PRE_SECH,
VAR_PRE_SECHQ,
VAR_PRE_SECQ,
VAR_PRE_SEPARATION,
VAR_PRE_SHIFT,
VAR_PRE_SHRED_RAD,
VAR_PRE_SHRED_LIN,
VAR_PRE_SIGMOID,
VAR_PRE_SIN,
VAR_PRE_SINEBLUR,
VAR_PRE_SINH,
VAR_PRE_SINHQ,
VAR_PRE_SINQ,
VAR_PRE_SINTRANGE,
VAR_PRE_SINUS_GRID,
VAR_PRE_SINUSOIDAL,
VAR_PRE_SINUSOIDAL3D,
VAR_PRE_SMARTSHAPE,
//VAR_PRE_SMARTCROP,
VAR_PRE_SPHER,
VAR_PRE_SPHEREBLUR,
VAR_PRE_SPHERICAL,
VAR_PRE_SPHERICAL3D,
VAR_PRE_SPHERICALN,
VAR_PRE_SPHERIVOID,
VAR_PRE_SPHYP3D,
VAR_PRE_SPIRAL,
VAR_PRE_SPIRAL_WING,
VAR_PRE_SPIROGRAPH,
VAR_PRE_SPLIT,
VAR_PRE_SPLIT_BRDR,
VAR_PRE_SPLITS,
VAR_PRE_SPLITS3D,
VAR_PRE_SQUARE,
VAR_PRE_SQUARES,
VAR_PRE_SQUARE3D,
VAR_PRE_SQUARIZE,
VAR_PRE_SQUIRREL,
VAR_PRE_SQUISH,
VAR_PRE_SSCHECKS,
VAR_PRE_STARBLUR,
VAR_PRE_STARBLUR2,
VAR_PRE_STRIPES,
VAR_PRE_STWIN,
VAR_PRE_SUPER_SHAPE,
VAR_PRE_SUPER_SHAPE3D,
VAR_PRE_SVF,
VAR_PRE_SWIRL,
VAR_PRE_SWIRL3,
VAR_PRE_SWIRL3R,
VAR_PRE_SYNTH,
VAR_PRE_TAN,
VAR_PRE_TANCOS,
VAR_PRE_TANGENT,
VAR_PRE_TANH,
VAR_PRE_TANHQ,
VAR_PRE_TANH_SPIRAL,
VAR_PRE_TANQ,
VAR_PRE_TARGET,
VAR_PRE_TARGET0,
VAR_PRE_TARGET2,
VAR_PRE_TAURUS,
VAR_PRE_TILE_HLP,
VAR_PRE_TILE_LOG,
VAR_PRE_TRADE,
VAR_PRE_TRUCHET,
VAR_PRE_TRUCHET_FILL,
VAR_PRE_TRUCHET_HEX_FILL,
VAR_PRE_TRUCHET_HEX_CROP,
VAR_PRE_TRUCHET_GLYPH,
VAR_PRE_TRUCHET_INV,
VAR_PRE_TRUCHET_KNOT,
VAR_PRE_TWINTRIAN,
VAR_PRE_TWO_FACE,
VAR_PRE_UNICORNGALOSHEN,
VAR_PRE_UNPOLAR,
VAR_PRE_VIBRATION,
VAR_PRE_VIBRATION2,
VAR_PRE_VIGNETTE,
VAR_PRE_VORON,
VAR_PRE_W,
VAR_PRE_WAFFLE,
VAR_PRE_WAVES,
VAR_PRE_WAVES2,
VAR_PRE_WAVES22,
VAR_PRE_WAVES23,
VAR_PRE_WAVES23D,
VAR_PRE_WAVES2B,
VAR_PRE_WAVES2_RADIAL,
VAR_PRE_WAVES3,
VAR_PRE_WAVES4,
VAR_PRE_WAVES42,
VAR_PRE_WAVESN,
VAR_PRE_WDISC,
VAR_PRE_WEDGE,
VAR_PRE_WEDGE_JULIA,
VAR_PRE_WEDGE_SPH,
VAR_PRE_WHORL,
VAR_PRE_X,
VAR_PRE_XERF,
VAR_PRE_XHEART,
VAR_PRE_XTRB,
VAR_PRE_Y,
VAR_PRE_Z,
VAR_PRE_ZBLUR,
VAR_PRE_ZCONE,
VAR_PRE_ZSCALE,
VAR_PRE_ZTRANSLATE,
VAR_POST_ARCH,
VAR_POST_ARCSECH,
VAR_POST_ARCSECH2,
VAR_POST_ARCSINH,
VAR_POST_ARCTANH,
VAR_POST_ASTERIA,
VAR_POST_AUGER,
VAR_POST_BARYCENTROID,
VAR_POST_BCIRCLE,
VAR_POST_BCOLLIDE,
VAR_POST_BENT,
VAR_POST_BENT2,
VAR_POST_BIPOLAR,
VAR_POST_BISPLIT,
VAR_POST_BLADE,
VAR_POST_BLADE3D,
VAR_POST_BLOB,
VAR_POST_BLOB2,
VAR_POST_BLOB3D,
VAR_POST_BLOCK,
VAR_POST_BLOCKY,
VAR_POST_BLUR,
VAR_POST_BLUR_CIRCLE,
VAR_POST_BLUR_HEART,
VAR_POST_BLUR_LINEAR,
VAR_POST_BLUR_PIXELIZE,
VAR_POST_BLUR_SQUARE,
VAR_POST_BLUR_ZOOM,
VAR_POST_BLUR3D,
VAR_POST_BMOD,
VAR_POST_BOARDERS,
VAR_POST_BOARDERS2,
VAR_POST_BSWIRL,
VAR_POST_BTRANSFORM,
VAR_POST_BUBBLE,
VAR_POST_BUBBLE2,
VAR_POST_BUBBLET3D,
VAR_POST_BUTTERFLY,
VAR_POST_BWRAPS,
VAR_POST_BWRAPS_RAND,
VAR_POST_CARDIOID,
VAR_POST_CELL,
VAR_POST_CHECKS,
VAR_POST_CIRCLEBLUR,
VAR_POST_CIRCLECROP,
VAR_POST_CIRCLECROP2,
VAR_POST_CIRCLELINEAR,
VAR_POST_CIRCLERAND,
VAR_POST_CIRCLESPLIT,
VAR_POST_CIRCLETRANS1,
VAR_POST_CIRCLE_RAND,
VAR_POST_CIRCLIZE,
VAR_POST_CIRCLIZE2,
VAR_POST_CIRCUS,
VAR_POST_COLLIDEOSCOPE,
VAR_POST_CONCENTRIC,
VAR_POST_CONIC,
VAR_POST_COS,
VAR_POST_COS_WRAP,
VAR_POST_COSH,
VAR_POST_COSHQ,
VAR_POST_COSINE,
VAR_POST_COSQ,
VAR_POST_COT,
VAR_POST_COTH,
VAR_POST_COTH_SPIRAL,
VAR_POST_COTHQ,
VAR_POST_COTQ,
VAR_POST_CPOW,
VAR_POST_CPOW2,
VAR_POST_CPOW3,
VAR_POST_CRACKLE,
VAR_POST_CRACKLE2,
VAR_POST_CRESCENTS,
VAR_POST_CROB,
VAR_POST_CROP,
VAR_POST_CROPN,
VAR_POST_CROSS,
VAR_POST_CSC,
VAR_POST_CSCH,
VAR_POST_CSCHQ,
VAR_POST_CSCQ,
VAR_POST_CUBIC3D,
VAR_POST_CUBIC_LATTICE3D,
VAR_POST_CURL,
VAR_POST_CURL3D,
VAR_POST_CURL_SP,
VAR_POST_CURVATURE,
VAR_POST_CURVE,
VAR_POST_CYLINDER,
VAR_POST_CYLINDER2,
VAR_POST_DELTA_A,
VAR_POST_DEPTH,
VAR_POST_DEPTH_BLUR,
VAR_POST_DEPTH_BLUR2,
VAR_POST_DEPTH_GAUSSIAN,
VAR_POST_DEPTH_GAUSSIAN2,
VAR_POST_DEPTH_NGON,
VAR_POST_DEPTH_NGON2,
VAR_POST_DEPTH_SINE,
VAR_POST_DEPTH_SINE2,
VAR_POST_DIAMOND,
VAR_POST_DISC,
VAR_POST_DISC2,
VAR_POST_DISC3D,
VAR_POST_DRAGONFIRE,
VAR_POST_DUST,
VAR_POST_D_SPHERICAL,
VAR_POST_ECLIPSE,
VAR_POST_ECOLLIDE,
VAR_POST_EDISC,
VAR_POST_EJULIA,
VAR_POST_ELLIPTIC,
VAR_POST_EMOD,
VAR_POST_EMOTION,
VAR_POST_ENNEPERS,
VAR_POST_EPISPIRAL,
VAR_POST_EPUSH,
VAR_POST_ERF,
VAR_POST_EROTATE,
VAR_POST_ESCALE,
VAR_POST_ESCHER,
VAR_POST_ESTIQ,
VAR_POST_ESWIRL,
VAR_POST_EX,
VAR_POST_EXCINIS,
VAR_POST_EXP,
VAR_POST_EXP2,
VAR_POST_EXPO,
VAR_POST_EXPONENTIAL,
VAR_POST_EXTRUDE,
VAR_POST_EYEFISH,
VAR_POST_FALLOFF,
VAR_POST_FALLOFF2,
VAR_POST_FALLOFF3,
VAR_POST_FAN,
VAR_POST_FAN2,
VAR_POST_FARBLUR,
VAR_POST_FDISC,
VAR_POST_FIBONACCI,
VAR_POST_FIBONACCI2,
VAR_POST_FISHEYE,
VAR_POST_FLATTEN,
VAR_POST_FLIP_CIRCLE,
VAR_POST_FLIP_X,
VAR_POST_FLIP_Y,
VAR_POST_FLOWER,
VAR_POST_FLOWER_DB,
VAR_POST_FLUX,
VAR_POST_FOCI,
VAR_POST_FOCI3D,
VAR_POST_FOCI_P,
VAR_POST_FOURTH,
VAR_POST_FUNNEL,
VAR_POST_GAMMA,
VAR_POST_GAUSSIAN,
VAR_POST_GAUSSIAN_BLUR,
VAR_POST_GDOFFS,
VAR_POST_GLYNNIA,
VAR_POST_GLYNNIA2,
VAR_POST_GLYNNSIM1,
VAR_POST_GLYNNSIM2,
VAR_POST_GLYNNSIM3,
VAR_POST_GLYNNSIM4,
VAR_POST_GLYNNSIM5,
VAR_POST_GNARLY,
VAR_POST_GRIDOUT,
VAR_POST_HANDKERCHIEF,
VAR_POST_HEART,
VAR_POST_HEAT,
VAR_POST_HELICOID,
VAR_POST_HELIX,
VAR_POST_HEMISPHERE,
VAR_POST_HENON,
VAR_POST_HEXAPLAY3D,
VAR_POST_HEXCROP,
VAR_POST_HEXES,
VAR_POST_HEXNIX3D,
VAR_POST_HEX_MODULUS,
VAR_POST_HEX_RAND,
VAR_POST_HEX_TRUCHET,
VAR_POST_HO,
VAR_POST_HOLE,
VAR_POST_HORSESHOE,
VAR_POST_HYPERBOLIC,
VAR_POST_HYPERCROP,
VAR_POST_HYPERSHIFT,
VAR_POST_HYPERSHIFT2,
VAR_POST_HYPERTILE,
VAR_POST_HYPERTILE1,
VAR_POST_HYPERTILE2,
VAR_POST_HYPERTILE3D,
VAR_POST_HYPERTILE3D1,
VAR_POST_HYPERTILE3D2,
VAR_POST_IDISC,
VAR_POST_INKDROP,
VAR_POST_INTERFERENCE2,
VAR_POST_JAC_CN,
VAR_POST_JAC_DN,
VAR_POST_JAC_SN,
VAR_POST_JULIA,
VAR_POST_JULIA3D,
VAR_POST_JULIA3DQ,
VAR_POST_JULIA3DZ,
VAR_POST_JULIAC,
VAR_POST_JULIAN,
VAR_POST_JULIAN2,
VAR_POST_JULIAN3DX,
VAR_POST_JULIANAB,
VAR_POST_JULIAQ,
VAR_POST_JULIASCOPE,
VAR_POST_KALEIDOSCOPE,
VAR_POST_LAZYJESS,
VAR_POST_LAZYSUSAN,
VAR_POST_LAZY_TRAVIS,
VAR_POST_LENS,
VAR_POST_LINE,
VAR_POST_LINEAR,
VAR_POST_LINEAR_T,
VAR_POST_LINEAR_T3D,
//VAR_POST_LINEAR_XZ,
//VAR_POST_LINEAR_YZ,
VAR_POST_LINEAR3D,
VAR_POST_LISSAJOUS,
VAR_POST_LOG,
VAR_POST_LOG_DB,
VAR_POST_LOQ,
VAR_POST_LOONIE,
VAR_POST_LOONIE2,
VAR_POST_LOONIE3,
VAR_POST_LOONIE3D,
VAR_POST_LOZI,
VAR_POST_MASK,
VAR_POST_MCARPET,
VAR_POST_MIRROR_X,
VAR_POST_MIRROR_Y,
VAR_POST_MIRROR_Z,
VAR_POST_MOBIQ,
VAR_POST_MOBIUS,
VAR_POST_MOBIUS_STRIP,
VAR_POST_MOBIUSN,
VAR_POST_MODULUS,
VAR_POST_MODULUSX,
VAR_POST_MODULUSY,
VAR_POST_MURL,
VAR_POST_MURL2,
VAR_POST_NBLUR,
VAR_POST_NGON,
VAR_POST_NOISE,
VAR_POST_NPOLAR,
VAR_POST_OCTAGON,
VAR_POST_OCTAPOL,
VAR_POST_ORTHO,
VAR_POST_OSCILLOSCOPE,
VAR_POST_OSCILLOSCOPE2,
VAR_POST_OVOID,
VAR_POST_OVOID3D,
VAR_POST_PANORAMA1,
VAR_POST_PANORAMA2,
VAR_POST_PARABOLA,
VAR_POST_PDJ,
VAR_POST_PERSPECTIVE,
VAR_POST_PETAL,
VAR_POST_PHOENIX_JULIA,
VAR_POST_PIE,
VAR_POST_PIE3D,
VAR_POST_PIXEL_FLOW,
VAR_POST_POINCARE,
VAR_POST_POINCARE2,
VAR_POST_POINCARE3D,
VAR_POST_POINT_SYMMETRY,
VAR_POST_POLAR,
VAR_POST_POLAR2,
VAR_POST_POLYNOMIAL,
VAR_POST_POPCORN,
VAR_POST_POPCORN2,
VAR_POST_POPCORN23D,
VAR_POST_POW_BLOCK,
VAR_POST_POWER,
VAR_POST_PRESSURE_WAVE,
VAR_POST_PROJECTIVE,
VAR_POST_PROSE3D,
VAR_POST_PSPHERE,
VAR_POST_PULSE,
VAR_POST_Q_ODE,
VAR_POST_RADIAL_BLUR,
VAR_POST_RAND_CUBES,
VAR_POST_RATIONAL3,
VAR_POST_RAYS,
VAR_POST_RAYS1,
VAR_POST_RAYS2,
VAR_POST_RAYS3,
VAR_POST_RBLUR,
VAR_POST_RECTANGLES,
VAR_POST_RINGS,
VAR_POST_RINGS2,
VAR_POST_RIPPLE,
VAR_POST_RIPPLED,
VAR_POST_ROTATE,
VAR_POST_ROTATE_X,
VAR_POST_ROTATE_Y,
VAR_POST_ROTATE_Z,
VAR_POST_ROUNDSPHER,
VAR_POST_ROUNDSPHER3D,
VAR_POST_SCRY,
VAR_POST_SCRY2,
VAR_POST_SCRY3D,
VAR_POST_SEC,
VAR_POST_SECANT2,
VAR_POST_SECH,
VAR_POST_SECHQ,
VAR_POST_SECQ,
VAR_POST_SEPARATION,
VAR_POST_SHIFT,
VAR_POST_SHRED_RAD,
VAR_POST_SHRED_LIN,
VAR_POST_SIGMOID,
VAR_POST_SIN,
VAR_POST_SINEBLUR,
VAR_POST_SINH,
VAR_POST_SINHQ,
VAR_POST_SINQ,
VAR_POST_SINTRANGE,
VAR_POST_SINUS_GRID,
VAR_POST_SINUSOIDAL,
VAR_POST_SINUSOIDAL3D,
VAR_POST_SMARTSHAPE,
VAR_POST_SMARTCROP,
VAR_POST_SPHER,
VAR_POST_SPHEREBLUR,
VAR_POST_SPHERICAL,
VAR_POST_SPHERICAL3D,
VAR_POST_SPHERICALN,
VAR_POST_SPHERIVOID,
VAR_POST_SPHYP3D,
VAR_POST_SPIRAL,
VAR_POST_SPIRAL_WING,
VAR_POST_SPIROGRAPH,
VAR_POST_SPLIT,
VAR_POST_SPLIT_BRDR,
VAR_POST_SPLITS,
VAR_POST_SPLITS3D,
VAR_POST_SQUARE,
VAR_POST_SQUARES,
VAR_POST_SQUARE3D,
VAR_POST_SQUARIZE,
VAR_POST_SQUIRREL,
VAR_POST_SQUISH,
VAR_POST_SSCHECKS,
VAR_POST_STARBLUR,
VAR_POST_STARBLUR2,
VAR_POST_STRIPES,
VAR_POST_STWIN,
VAR_POST_SUPER_SHAPE,
VAR_POST_SUPER_SHAPE3D,
VAR_POST_SVF,
VAR_POST_SWIRL,
VAR_POST_SWIRL3,
VAR_POST_SWIRL3R,
VAR_POST_SYNTH,
VAR_POST_TAN,
VAR_POST_TANCOS,
VAR_POST_TANGENT,
VAR_POST_TANH,
VAR_POST_TANHQ,
VAR_POST_TANH_SPIRAL,
VAR_POST_TANQ,
VAR_POST_TARGET,
VAR_POST_TARGET0,
VAR_POST_TARGET2,
VAR_POST_TAURUS,
VAR_POST_TILE_HLP,
VAR_POST_TILE_LOG,
VAR_POST_TRADE,
VAR_POST_TRUCHET,
VAR_POST_TRUCHET_FILL,
VAR_POST_TRUCHET_HEX_FILL,
VAR_POST_TRUCHET_HEX_CROP,
VAR_POST_TRUCHET_GLYPH,
VAR_POST_TRUCHET_INV,
VAR_POST_TRUCHET_KNOT,
VAR_POST_TWINTRIAN,
VAR_POST_TWO_FACE,
VAR_POST_UNICORNGALOSHEN,
VAR_POST_UNPOLAR,
VAR_POST_VIBRATION,
VAR_POST_VIBRATION2,
VAR_POST_VIGNETTE,
VAR_POST_VORON,
VAR_POST_W,
VAR_POST_WAFFLE,
VAR_POST_WAVES,
VAR_POST_WAVES2,
VAR_POST_WAVES22,
VAR_POST_WAVES23,
VAR_POST_WAVES23D,
VAR_POST_WAVES2B,
VAR_POST_WAVES2_RADIAL,
VAR_POST_WAVES3,
VAR_POST_WAVES4,
VAR_POST_WAVES42,
VAR_POST_WAVESN,
VAR_POST_WDISC,
VAR_POST_WEDGE,
VAR_POST_WEDGE_JULIA,
VAR_POST_WEDGE_SPH,
VAR_POST_WHORL,
VAR_POST_X,
VAR_POST_XERF,
VAR_POST_XHEART,
VAR_POST_XTRB,
VAR_POST_Y,
VAR_POST_Z,
VAR_POST_ZBLUR,
VAR_POST_ZCONE,
VAR_POST_ZSCALE,
VAR_POST_ZTRANSLATE,
//Direct color variations are special.
VAR_DC_BUBBLE,
VAR_DC_CARPET,
VAR_DC_CUBE,
VAR_DC_CYLINDER,
VAR_DC_GRIDOUT,
VAR_DC_LINEAR,
VAR_DC_PERLIN,
VAR_DC_TRIANGLE,
VAR_DC_ZTRANSL,
VAR_PRE_DC_BUBBLE,
VAR_PRE_DC_CARPET,
VAR_PRE_DC_CUBE,
VAR_PRE_DC_CYLINDER,
VAR_PRE_DC_GRIDOUT,
VAR_PRE_DC_LINEAR,
VAR_PRE_DC_PERLIN,
VAR_PRE_DC_TRIANGLE,
VAR_PRE_DC_ZTRANSL,
VAR_POST_DC_BUBBLE,
VAR_POST_DC_CARPET,
VAR_POST_DC_CUBE,
VAR_POST_DC_CYLINDER,
VAR_POST_DC_GRIDOUT,
VAR_POST_DC_LINEAR,
VAR_POST_DC_PERLIN,
VAR_POST_DC_TRIANGLE,
VAR_POST_DC_ZTRANSL,
LAST_VAR = eVariationId::VAR_POST_DC_ZTRANSL + 1
};
/// <summary>
/// Translated and precalculated values that get passed to each variation's virtual function.
/// Note that this must be passed in and not a member because multiple threads will be calling
/// the variation functions simultaneously. Each thread will get its own IteratorHelper object.
/// Template argument expected to be float or double.
/// </summary>
template <typename T>
class EMBER_API IteratorHelper
{
public:
v2T m_Color;
T m_TransX, m_TransY, m_TransZ;//Translated point gotten by applying the affine transform to the input point gotten from the output of the previous iteration (excluding final).
T m_PrecalcSumSquares;//Precalculated value of the sum of the squares of the translated point.
T m_PrecalcSqrtSumSquares;//Precalculated value of the square root of m_PrecalcSumSquares.
T m_PrecalcCosa;//Precalculated value of m_TransY / m_PrecalcSqrtSumSquares.
T m_PrecalcSina;//Precalculated value of m_TransX / m_PrecalcSqrtSumSquares.
T m_PrecalcAtanxy;//Precalculated value of atan2(m_TransX, m_TransY).
T m_PrecalcAtanyx;//Precalculated value of atan2(m_TransY, m_TransX).
v4T In, Out;
};
/// <summary>
/// The base variation class from which all variations will derive.
/// Each has a unique ID, name and weight, as well as a virtual function Func() which
/// does the actual calculations.
/// Each also has boolean values that specify whether precalculations are needed.
/// These precalc flags are used by the parent Xform to determine which values to
/// precalculate in each iteration.
/// Template argument expected to be float or double.
/// </summary>
template <class T>
class EMBER_API Variation
{
public:
/// <summary>
/// Constructor which takes parameters.
/// </summary>
/// <param name="name">The unique name of the variation</param>
/// <param name="id">The unique ID of the variation</param>
/// <param name="weight">The weight. Default: 1.</param>
/// <param name="needPrecalcSumSquares">Whether it uses the precalc sum squares value in its calculations. Default: false.</param>
/// <param name="needPrecalcSqrtSumSquares">Whether it uses the sqrt precalc sum squares value in its calculations. Default: false.</param>
/// <param name="needPrecalcAngles">Whether it uses the precalc sin and cos values in its calculations. Default: false.</param>
/// <param name="needPrecalcAtanXY">Whether it uses the precalc atan XY value in its calculations. Default: false.</param>
/// <param name="needPrecalcAtanYX">Whether it uses the precalc atan YX value in its calculations. Default: false.</param>
Variation(const char* name, eVariationId id, T weight = 1.0,
bool needPrecalcSumSquares = false,
bool needPrecalcSqrtSumSquares = false,
bool needPrecalcAngles = false,
bool needPrecalcAtanXY = false,
bool needPrecalcAtanYX = false)
: m_Name(name)//Omit unnecessary default constructor call.
{
m_Xform = nullptr;
m_VariationId = id;
m_Weight = weight;
m_NeedPrecalcSumSquares = needPrecalcSumSquares;
m_NeedPrecalcSqrtSumSquares = needPrecalcSqrtSumSquares;
m_NeedPrecalcAngles = needPrecalcAngles;
m_NeedPrecalcAtanXY = needPrecalcAtanXY;
m_NeedPrecalcAtanYX = needPrecalcAtanYX;
//Make absolutely sure that flag logic makes sense.
if (m_NeedPrecalcSqrtSumSquares)
m_NeedPrecalcSumSquares = true;
if (m_NeedPrecalcAngles)
{
m_NeedPrecalcSumSquares = true;
m_NeedPrecalcSqrtSumSquares = true;
}
m_PrePostAssignType = eVariationAssignType::ASSIGNTYPE_SET;
SetType();
}
/// <summary>
/// Default copy constructor.
/// </summary>
/// <param name="variation">The Variation object to copy</param>
Variation(const Variation<T>& variation)
{
Variation<T>::operator=<T>(variation);
}
/// <summary>
/// Copy constructor to copy a Variation object of type U.
/// </summary>
/// <param name="variation">The Variation object to copy</param>
template <typename U>
Variation(const Variation<U>& variation)
{
Variation<T>::operator=<U>(variation);
}
/// <summary>
/// Empty virtual destructor.
/// Note that even though this is empty, it must be present
/// and be virtual for the derived classes to properly get destroyed.
/// </summary>
virtual ~Variation()
{
}
/// <summary>
/// Default assignment operator.
/// </summary>
/// <param name="variation">The Variation object to copy</param>
Variation<T>& operator = (const Variation<T>& variation)
{
if (this != &variation)
Variation<T>::operator=<T>(variation);
return *this;
}
/// <summary>
/// Assignment operator to assign a Variation object of type U.
/// </summary>
/// <param name="variation">The Variation object to copy.</param>
/// <returns>Reference to updated self</returns>
template <typename U>
Variation<T>& operator = (const Variation<U>& variation)
{
m_Name = variation.Name();
m_VarType = variation.VarType();
m_PrePostAssignType = variation.AssignType();
m_VariationId = variation.VariationId();
m_Weight = T(variation.m_Weight);
m_Xform = typeid(T) == typeid(U) ? const_cast<Xform<T>*>(reinterpret_cast<const Xform<T>*>(variation.ParentXform())) : nullptr;
m_NeedPrecalcSumSquares = variation.NeedPrecalcSumSquares();
m_NeedPrecalcSqrtSumSquares = variation.NeedPrecalcSqrtSumSquares();
m_NeedPrecalcAngles = variation.NeedPrecalcAngles();
m_NeedPrecalcAtanXY = variation.NeedPrecalcAtanXY();
m_NeedPrecalcAtanYX = variation.NeedPrecalcAtanYX();
return *this;
}
/// <summary>
/// Per-variation precalc used for pre and post variations.
/// </summary>
/// <param name="iteratorHelper">The helper to read values from in the case of pre, and store precalc values to in both cases.</param>
void PrePostPrecalcHelper(IteratorHelper<T>& iteratorHelper)
{
if (m_NeedPrecalcSumSquares)
{
iteratorHelper.m_PrecalcSumSquares = SQR(iteratorHelper.In.x) + SQR(iteratorHelper.In.y);
if (m_NeedPrecalcSqrtSumSquares)
{
iteratorHelper.m_PrecalcSqrtSumSquares = std::sqrt(iteratorHelper.m_PrecalcSumSquares);
if (m_NeedPrecalcAngles)
{
iteratorHelper.m_PrecalcSina = iteratorHelper.In.y / Zeps(iteratorHelper.m_PrecalcSqrtSumSquares);
iteratorHelper.m_PrecalcCosa = iteratorHelper.In.x / Zeps(iteratorHelper.m_PrecalcSqrtSumSquares);
}
}
}
if (m_NeedPrecalcAtanXY)
iteratorHelper.m_PrecalcAtanxy = std::atan2(iteratorHelper.In.x, iteratorHelper.In.y);
if (m_NeedPrecalcAtanYX)
iteratorHelper.m_PrecalcAtanyx = std::atan2(iteratorHelper.In.y, iteratorHelper.In.x);
}
/// <summary>
/// Per-variation precalc OpenCL string used for pre and post variations.
/// </summary>
/// <returns>The per-variation OpenCL precalc string</returns>
string PrePostPrecalcOpenCLString() const
{
ostringstream ss;
if (m_NeedPrecalcSumSquares)
{
ss << "\tprecalcSumSquares = SQR(vIn.x) + SQR(vIn.y);\n";
if (m_NeedPrecalcSqrtSumSquares)
{
ss << "\tprecalcSqrtSumSquares = sqrt(precalcSumSquares);\n";
if (m_NeedPrecalcAngles)
{
ss << "\tprecalcSina = vIn.y / Zeps(precalcSqrtSumSquares);\n";
ss << "\tprecalcCosa = vIn.x / Zeps(precalcSqrtSumSquares);\n";
}
}
}
if (m_NeedPrecalcAtanXY)
ss << "\tprecalcAtanxy = atan2(vIn.x, vIn.y);\n";
if (m_NeedPrecalcAtanYX)
ss << "\tprecalcAtanyx = atan2(vIn.y, vIn.x);\n";
if (NeedAnyPrecalc())
ss << "\n";
return ss.str();
}
/// <summary>
/// Returns an OpenCL string for the fields in this variation
/// that change during iterations.
/// Note these are different than regular variation parameters,
/// and thus require a completely different solution.
/// </summary>
/// <returns></returns>
virtual string StateOpenCLString() const
{
return "";
}
/// <summary>
/// Initialize the state variables contained in the passed in array.
/// </summary>
/// <param name="t">The pointer to the state variables.</param>
/// <param name="index">The offset in the pointer where the data begins.</param>
virtual void InitStateVars(T* t, size_t& index)
{
}
/// <summary>
/// Returns an OpenCL string for the initialization of the fields in this variation
/// that change during iterations.
/// Note these are different than regular variation parameters,
/// and thus require a completely different solution.
/// </summary>
/// <returns></returns>
virtual string StateInitOpenCLString() const
{
return "";
}
/// <summary>
/// Return the name and weight of the variation as a string.
/// </summary>
/// <returns>The name and weight of the variation</returns>
virtual string ToString() const
{
ostringstream ss;
ss << m_Name << "(" << m_Weight << ")";
return ss.str();
}
/// <summary>
/// Abstract copy function. Derived classes must implement.
/// </summary>
/// <returns>A copy of this object</returns>
virtual Variation<T>* Copy() const = 0;
/// <summary>
/// Create a new Variation<float>, store it in the pointer reference passed in and
/// copy the this Variation's values into it.
/// Note this is a severe hack to overcome two shortcomings in C++.
/// One is that templated functions cannot be virtual.
/// The second is that function overloading only works when parameters differ, not just return types.
/// In an ideal world, all copy functionality would be consolidated into a single function that looked like:
/// template <typename U> virtual Variation<U> Copy();
/// Since that isn't possible, the only way to do what's needed is to create two functions to do this, one for
/// Variation<float> and another for Variation<double>.
/// This further offends design sensiblities since it requires this template class to know which types it's going to
/// be instantiated for. Sadly, there is no alternative and it must be done this way. Fortunately, we know it will
/// only ever be used with float and double.
/// </summary>
/// <param name="var">A reference to a pointer which will store the newly created Variation<float>*</param>
virtual void Copy(Variation<float>*& var) const = 0;
#ifdef DO_DOUBLE
/// <summary>
/// See description for Copy(Variation<float>*& var).
/// </summary>
/// <param name="var">A reference to a pointer which will store the newly created Variation<double>*</param>
virtual void Copy(Variation<double>*& var) const = 0;
#endif
/// <summary>
/// Abstract function where the actual work takes place. Derived classes must implement.
/// </summary>
/// <param name="helper">The IteratorHelper object which holds translated and precalculated values</param>
/// <param name="outPoint">The point to store the result in</param>
/// <param name="rand">The random number generator to use.</param>
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) = 0;
/// <summary>
/// Return a string which performs the equivalent calculation in Func(), but on the GPU in OpenCL.
/// Derived classes will implement this.
/// </summary>
/// <returns>The OpenCL string to perform the equivalent calculation on the GPU in OpenCL</returns>
virtual string OpenCLString() const { return ""; }
/// <summary>
/// If the OpenCL string depends on any global functions specific to this variation, return their names.
/// </summary>
/// <returns>The names for global OpenCL functions specific to this variation</returns>
virtual vector<string> OpenCLGlobalFuncNames() const { return vector<string>(); }
/// <summary>
/// If the OpenCL string depends on any global static data specific to this variation, and possibly shared among others, return their names.
/// </summary>
/// <returns>The names for global OpenCL data specific to this variation</returns>
virtual vector<string> OpenCLGlobalDataNames() const { return vector<string>(); }
/// <summary>
/// If the OpenCL string depends on any functions specific to this variation, return them.
/// </summary>
/// <returns>The OpenCL string for functions specific to this variation</returns>
virtual string OpenCLFuncsString() const { return ""; }
/// <summary>
/// In addition to the standard precalculation stored in the IteratorHelper object, some
/// variations have additional precalculation work to do that can save processing time while iterating.
/// For most this is left empty, however a few will override.
/// </summary>
virtual void Precalc() { }
/// <summary>
/// When creating random embers, the variations are placed in a random state.
/// For most this base implementation will be used, however a few will override.
/// </summary>
/// <param name="rand">The rand.</param>
virtual void Random(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
m_Weight = rand.Frand11<T>();
}
/// <summary>
/// Returns the string prefix to be used with params and the variation name.
/// </summary>
/// <returns>pre_, post_ or the empty string</returns>
string Prefix() const
{
if (m_VarType == eVariationType::VARTYPE_PRE)
return "pre_";
else if (m_VarType == eVariationType::VARTYPE_POST)
return "post_";
else
return "";
}
/// <summary>
/// Returns the base name of the variation without the "pre_" or "post_" prefix.
/// </summary>
/// <returns>The base name of the variation</returns>
string BaseName() const
{
string prefix = Prefix();
if (prefix != "" && m_Name.find(prefix) == 0)
return m_Name.substr(prefix.size(), m_Name.size() - prefix.size());
else
return m_Name;
}
/// <summary>
/// Accessors.
/// </summary>
inline bool NeedPrecalcSumSquares() const { return m_NeedPrecalcSumSquares; }
inline bool NeedPrecalcSqrtSumSquares() const { return m_NeedPrecalcSqrtSumSquares; }
inline bool NeedPrecalcAngles() const { return m_NeedPrecalcAngles; }
inline bool NeedPrecalcAtanXY() const { return m_NeedPrecalcAtanXY; }
inline bool NeedPrecalcAtanYX() const { return m_NeedPrecalcAtanYX; }
inline bool NeedAnyPrecalc() const { return NeedPrecalcSumSquares() || NeedPrecalcSqrtSumSquares() || NeedPrecalcAngles() || NeedPrecalcAtanXY() || NeedPrecalcAtanYX(); }
eVariationId VariationId() const { return m_VariationId; }
string Name() const { return m_Name; }
eVariationType VarType() const { return m_VarType; }
eVariationAssignType AssignType() const { return m_PrePostAssignType; }
const Xform<T>* ParentXform() const { return m_Xform; }
void ParentXform(Xform<T>* xform) { m_Xform = xform; }
intmax_t IndexInXform() const { return m_Xform ? m_Xform->GetVariationIndex(const_cast<Variation<T>*>(this)) : -1; }
intmax_t XformIndexInEmber() const { return m_Xform ? m_Xform->IndexInParentEmber() : -1; }
virtual size_t StateParamCount() const { return 0; }
T m_Weight;//The weight of the variation.
protected:
/// <summary>
/// Sets the type of the variation depending on whether the name starts with "pre_",
/// "post_" or neither.
/// </summary>
void SetType()
{
if (m_Name.find("pre_") == 0)
m_VarType = eVariationType::VARTYPE_PRE;
else if (m_Name.find("post_") == 0)
m_VarType = eVariationType::VARTYPE_POST;
else
m_VarType = eVariationType::VARTYPE_REG;
}
/// <summary>
/// Return the default Z coordinate assignment value depending on the type of variation and its assign type.
/// </summary>
/// <param name="helper">The helper used to retrieve the input Z coordinate.</param>
/// <returns>The appropriate Z value.</returns>
T DefaultZ(const IteratorHelper<T>& helper) const
{
return m_VarType == eVariationType::VARTYPE_REG ? 0 : (m_PrePostAssignType == eVariationAssignType::ASSIGNTYPE_SET ? helper.In.z : 0);
}
/// <summary>
/// OpenCL equivalent of DefaultZ().
/// </summary>
/// <returns>The OpenCL string needed to make the proper Z coordinate assignment</returns>
string DefaultZCl() const
{
return m_VarType == eVariationType::VARTYPE_REG ? "0;\n" : (m_PrePostAssignType == eVariationAssignType::ASSIGNTYPE_SET ? "vIn.z;\n" : "0;\n");
}
string WeightDefineString() const
{
return WEIGHT_PREFIX + std::to_string(XformIndexInEmber()) + "_" + std::to_string(IndexInXform()) + "]";
}
Xform<T>* m_Xform;//The parent Xform that this variation is a child of.
eVariationId m_VariationId;//The unique ID of this variation.
string m_Name;//The unique name of this variation.
eVariationType m_VarType;//The type of variation: regular, pre or post.
eVariationAssignType m_PrePostAssignType;//Whether to assign the results for pre/post, or sum them.
protected:
bool m_NeedPrecalcSumSquares;//Whether this variation uses the precalc sum squares value in its calculations.
bool m_NeedPrecalcSqrtSumSquares;//Whether it uses the sqrt precalc sum squares value in its calculations.
bool m_NeedPrecalcAngles;//Whether it uses the precalc sin and cos values in its calculations.
bool m_NeedPrecalcAtanXY;//Whether it uses the precalc atan XY value in its calculations.
bool m_NeedPrecalcAtanYX;//Whether it uses the precalc atan YX value in its calculations.
};
/// <summary>
/// The type of parameter represented by ParamWithName<T>.
/// This allows restricting of certain parameters to sensible values.
/// </summary>
enum class eParamType : et
{
REAL,
REAL_CYCLIC,
REAL_NONZERO,
INTEGER,
INTEGER_NONZERO
};
/// <summary>
/// Thin wrapper to allow << operator on param type.
/// </summary>
/// <param name="stream">The stream to insert into</param>
/// <param name="t">The type whose string representation will be inserted into the stream</param>
/// <returns></returns>
static std::ostream& operator<<(std::ostream& stream, const eParamType& t)
{
switch (t)
{
case eParamType::REAL:
stream << "real";
break;
case eParamType::REAL_CYCLIC:
stream << "cyclic";
break;
case eParamType::REAL_NONZERO:
stream << "non-zero";
break;
case eParamType::INTEGER:
stream << "integer";
break;
case eParamType::INTEGER_NONZERO:
stream << "integer non-zero";
break;
default:
stream << "error";
break;
}
return stream;
}
template <typename T> class ParametricVariation;
/// <summary>
/// Parametric variations use parameters in addition to weight.
/// These values are stored in members of classes derived from ParametricVariation,
/// however for easy access, pointers to them are also stored in a vector
/// of ParamWithName in ParametricVariation.
/// Each of these takes the form of a name string and a pointer to a value.
/// Also, some of them can be considered precalculated values, rather than
/// formal parameters.
/// Further, some can change state between iterations.
/// The constructors for each case are deliberately different to prevent errors.
/// This class encapsulates a single parameter.
/// Template argument expected to be float or double.
/// </summary>
template <typename T>
class EMBER_API ParamWithName
{
friend ParametricVariation<T>;
public:
/// <summary>
/// Default constructor.
/// </summary>
ParamWithName()
{
Init(nullptr, "", 0, eParamType::REAL, TLOW, TMAX);
}
/// <summary>
/// Constructor for a precalc param that takes arguments.
/// </summary>
/// <param name="isPrecalc">Whether the parameter is actually a precalculated value. Always true.</param>
/// <param name="param">A pointer to the parameter</param>
/// <param name="name">The name of the parameter</param>
/// <param name="size">The length of the underlying memory in bytes. Needed for array types. Default: sizeof(T).</param>
ParamWithName(bool isPrecalc,
T* param,
string name,
size_t size = sizeof(T))
{
Init(param, name, 0, eParamType::REAL, TLOW, TMAX, true, false, size);
}
/// <summary>
/// Constructor for a state param that takes arguments.
/// </summary>
/// <param name="isPrecalc">Whether the parameter is actually a precalculated value. Always true.</param>
/// <param name="isState">Whether the parameter changes state between iterations. Always true.</param>
/// <param name="param">A pointer to the parameter</param>
/// <param name="name">The name of the parameter</param>
ParamWithName(bool isPrecalc,
bool isState,
T* param,
string name)
{
Init(param, name, 0, eParamType::REAL, TLOW, TMAX, true, true);
}
/// <summary>
/// Constructor for a non-precalc param that takes arguments.
/// </summary>
/// <param name="param">A pointer to the parameter</param>
/// <param name="name">The name of the parameter</param>
/// <param name="def">The default value of the parameter</param>
/// <param name="type">The type of the parameter</param>
/// <param name="min">The minimum value the parameter can be</param>
/// <param name="max">The maximum value the parameter can be</param>
ParamWithName(T* param, const string& name, T def = 0, eParamType type = eParamType::REAL, T min = TLOW, T max = TMAX)
{
Init(param, name, def, type, min, max);
}
/// <summary>
/// Copy constructor.
/// Note this constructor does not take an additional template parameter
/// like the others do. This is because there is not way to assign the
/// param pointer from one type to another. Luckily, such functionality is not needed
/// with this class.
/// </summary>
/// <param name="paramWithName">The ParamWithName object to copy</param>
ParamWithName(const ParamWithName<T>& paramWithName)
{
*this = paramWithName;
}
/// <summary>
/// Assignment operator.
/// Note this assignment operator does not take an additional template parameter
/// like the others do. This is because there is not way to assign the
/// param pointer from one type to another. Luckily, such functionality is not needed
/// with this class.
/// </summary>
/// <param name="paramWithName">The ParamWithName object to copy.</param>
/// <returns>Reference to updated self</returns>
ParamWithName<T>& operator = (const ParamWithName<T>& paramWithName)
{
if (this != &paramWithName)
{
m_Param = paramWithName.m_Param;
m_Def = paramWithName.m_Def;
m_Min = paramWithName.m_Min;
m_Max = paramWithName.m_Max;
m_Type = paramWithName.m_Type;
m_Name = paramWithName.m_Name;
m_IsPrecalc = paramWithName.m_IsPrecalc;
m_IsState = paramWithName.m_IsState;
m_Size = paramWithName.m_Size;
}
return *this;
}
/// <summary>
/// Constructor that takes arguments.
/// </summary>
/// <param name="param">A pointer to the parameter</param>
/// <param name="name">The name of the parameter</param>
/// <param name="def">The default value of the parameter</param>
/// <param name="type">The type of the parameter</param>
/// <param name="min">The minimum value the parameter can be</param>
/// <param name="max">The maximum value the parameter can be</param>
/// <param name="isPrecalc">Whether the parameter is actually a precalculated value. Default: false.</param>
/// <param name="isState">Whether the parameter changes state between iterations. Default: false.</param>
/// <param name="size">The length of the underlying memory in bytes. Needed for array types. Default: sizeof(T).</param>
void Init(T* param, const string& name, T def = 0, eParamType type = eParamType::REAL, T min = TLOW, T max = TMAX, bool isPrecalc = false, bool isState = false, size_t size = sizeof(T))
{
m_Param = param;
m_Def = def;
m_Min = min;
m_Max = max;
m_Type = type;
m_Name = name;
m_IsPrecalc = isPrecalc;
m_IsState = isState;
m_Size = size;
Set(m_Def);//Initial value.
}
/// <summary>
/// Set this parameter to the val.
/// Depending on the type that was specified in the constructor, various restrictions
/// will be put on the value.
/// </summary>
/// <param name="val">The value to set the parameter to</param>
void Set(T val)
{
switch (m_Type)
{
case eParamType::REAL:
{
*m_Param = std::max(std::min(val, m_Max), m_Min);
break;
}
case eParamType::REAL_CYCLIC :
{
if (val > m_Max)
*m_Param = m_Min + fmod(val - m_Min, m_Max - m_Min);
else if (val < m_Min)
*m_Param = m_Max - fmod(m_Max - val, m_Max - m_Min);
else
*m_Param = val;
break;
}
case eParamType::REAL_NONZERO :
{
T vd = std::max(std::min(val, m_Max), m_Min);
if (IsNearZero(vd))
*m_Param = EPS * VarFuncs<T>::SignNz(vd);
else
*m_Param = vd;
break;
}
case eParamType::INTEGER :
{
*m_Param = T(int(std::max(std::min<T>(T(Floor<T>(val + T(0.5))), m_Max), m_Min)));
break;
}
case eParamType::INTEGER_NONZERO :
default:
{
int vi = int(std::max(std::min<T>(T(Floor<T>(val + T(0.5))), m_Max), m_Min));
if (vi == 0)
vi = int(VarFuncs<T>::SignNz(val));
*m_Param = T(vi);
break;
}
}
}
/// <summary>
/// Return the values of the ParamWithName as a string.
/// </summary>
/// <returns>The ParamWithName values as a string</returns>
string ToString() const
{
ostringstream ss;
ss << "Param Name: " << m_Name << "\n"
<< "Param Pointer: " << m_Param << "\n"
<< "Param Value: " << *m_Param << "\n"
<< "Param Def: " << m_Def << "\n"
<< "Param Min: " << m_Min << "\n"
<< "Param Max: " << m_Max << "\n"
<< "Param Type: " << m_Type << "\n"
<< "Is Precalc: " << m_IsPrecalc << "\n"
<< "Is State: " << m_IsState << "\n"
<< "Size: " << m_Size << "\n";
return ss.str();
}
/// <summary>
/// Accessors.
/// </summary>
T* Param() const { return m_Param; }
T ParamVal() const { return *m_Param; }
T Def() const { return m_Def; }
T Min() const { return m_Min; }
T Max() const { return m_Max; }
eParamType Type() const { return m_Type; }
string Name() const { return m_Name; }
bool IsPrecalc() const { return m_IsPrecalc; }
bool IsState() const { return m_IsState; }
size_t Size() const { return m_Size; }
private:
T* m_Param;//Pointer to the parameter value.
T m_Def;//The default value of the parameter.
T m_Min;//The minimum value the parameter can be.
T m_Max;//The maximum value the parameter can be.
eParamType m_Type;//The type of the parameter.
string m_Name;//Name of the parameter.
bool m_IsPrecalc;//Whether the parameter is actually a precalculated value.
bool m_IsState;//Whether the parameter changes state between iterations. This is also considered precalc.
size_t m_Size;//The size of the field in bytes. Default: sizeof(T).
};
#define VARUSINGS \
using Variation<T>::m_Weight; \
using Variation<T>::m_Xform; \
using Variation<T>::m_VariationId; \
using Variation<T>::m_Name; \
using Variation<T>::m_VarType; \
using Variation<T>::m_PrePostAssignType; \
using Variation<T>::SetType; \
using Variation<T>::IndexInXform; \
using Variation<T>::XformIndexInEmber; \
using Variation<T>::Prefix; \
using Variation<T>::Precalc; \
using Variation<T>::StateOpenCLString; \
using Variation<T>::InitStateVars; \
using Variation<T>::WeightDefineString; \
using Variation<T>::DefaultZ; \
using Variation<T>::DefaultZCl;
/// <summary>
/// Parametric variations use parameters in addition to weight.
/// These values are stored in members of derived classes, however
/// for easy access, pointers to them are also stored in a vector
/// of ParamWithName in this class.
/// Template argument expected to be float or double.
/// </summary>
template <typename T>
class EMBER_API ParametricVariation : public Variation<T>
{
public:
VARUSINGS
/// <summary>
/// Constructor which takes arguments and just passes them to the base class.
/// </summary>
/// <param name="name">The unique name of the variation</param>
/// <param name="id">The unique ID of the variation</param>
/// <param name="weight">The weight. Default: 1.</param>
/// <param name="needPrecalcSumSquares">Whether it uses the precalc sum squares value in its calculations. Default: false.</param>
/// <param name="needPrecalcSqrtSumSquares">Whether it uses the sqrt precalc sum squares value in its calculations. Default: false.</param>
/// <param name="needPrecalcAngles">Whether it uses the precalc sin and cos values in its calculations. Default: false.</param>
/// <param name="needPrecalcAtanXY">Whether it uses the precalc atan XY value in its calculations. Default: false.</param>
/// <param name="needPrecalcAtanYX">Whether it uses the precalc atan YX value in its calculations. Default: false.</param>
ParametricVariation(const char* name, eVariationId id, T weight = 1.0,
bool needPrecalcSumSquares = false,
bool needPrecalcSqrtSumSquares = false,
bool needPrecalcAngles = false,
bool needPrecalcAtanXY = false,
bool needPrecalcAtanYX = false)
: Variation<T>(name, id, weight,
needPrecalcSumSquares,
needPrecalcSqrtSumSquares,
needPrecalcAngles,
needPrecalcAtanXY,
needPrecalcAtanYX)
{
m_Params.reserve(5);
}
/// <summary>
/// Default copy constructor.
/// </summary>
/// <param name="var">The ParametricVariation object to copy</param>
ParametricVariation(const ParametricVariation<T>& var)
: Variation<T>(var)
{
//Derived classes will have to initialize the m_Params vector
//to the addresses of its members and then assign values from var.
m_Params.reserve(5);
}
/// <summary>
/// Copy constructor to copy a ParametricVariation object of type U.
/// </summary>
/// <param name="var">The ParametricVariation object to copy</param>
template <typename U>
ParametricVariation(const ParametricVariation<U>& var)
: Variation<T>(var)
{
//Derived classes will have to initialize the m_Params vector
//to the addresses of its members and then assign values from var.
m_Params.reserve(5);
}
/// <summary>
/// Empty virtual destructor.
/// Needed to eliminate warnings about inlining.
/// </summary>
virtual ~ParametricVariation()
{
}
/// <summary>
/// Determine whether the params vector contains a parameter with the specified name.
/// </summary>
/// <param name="name">The name to search for</param>
/// <returns>True if found, else false.</returns>
bool ContainsParam(const char* name)
{
bool b = false;
for (auto& param : m_Params)
{
if (!_stricmp(param.Name().c_str(), name))
{
b = true;
break;
}
}
return b;
}
/// <summary>
/// Get a pointer to a parameter value with the specified name.
/// </summary>
/// <param name="name">The name to search for</param>
/// <returns>A pointer to the parameter value if the name matched, else null.</returns>
T* GetParam(const char* name) const
{
for (auto& param : m_Params)
if (!_stricmp(param.Name().c_str(), name))
return param.Param();
return nullptr;
}
/// <summary>
/// Get a parameter value with the specified name.
/// </summary>
/// <param name="name">The name to search for</param>
/// <returns>A parameter value if the name matched, else 0.</returns>
T GetParamVal(const char* name) const
{
for (auto& param : m_Params)
if (!_stricmp(param.Name().c_str(), name))
return param.ParamVal();
return 0;
}
/// <summary>
/// Assign a value to the parameter with the specified name and call virtual Precalc() if found.
/// </summary>
/// <param name="name">The name of the parameter to assign to</param>
/// <param name="val">The value to assign</param>
/// <returns>True if the name matched, else false.</returns>
virtual bool SetParamVal(const char* name, T val)
{
bool b = false;
for (auto& param : m_Params)
{
if (!_stricmp(param.Name().c_str(), name))
{
param.Set(val);
this->Precalc();
b = true;
break;
}
}
return b;
}
/// <summary>
/// Assign a value to the parameter at the specified index and call virtual Precalc() if found.
/// </summary>
/// <param name="index">The index of the parameter to assign to</param>
/// <param name="val">The value to assign</param>
/// <returns>True if the index was in range, else false.</returns>
virtual bool SetParamVal(int index, T val)
{
bool b = false;
if (index < m_Params.size())
{
m_Params[index].Set(val);
this->Precalc();
b = true;
}
return b;
}
/// <summary>
/// Severe hack to get g++ to compile this.
/// </summary>
virtual void Precalc() override { }
/// <summary>
/// Place the parametric variation in a random state by setting all of the
/// non-precalc params to values between -1 and 1;
/// </summary>
/// <param name="rand">The rand.</param>
virtual void Random(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
Variation<T>::Random(rand);
for (auto& param : m_Params) param.Set(rand.Frand11<T>());
this->Precalc();
}
/// <summary>
/// Assign all 0 to all parameters and call virtual Precalc().
/// </summary>
void Clear()
{
for (auto& param : m_Params) *(param.Param()) = 0;
}
/// <summary>
/// Return a vector of all parameter names, optionally including precalcs.
/// </summary>
/// <param name="includePrecalcs">Whether to include the names of precalcs in the returned vector</param>
/// <returns>A vector of all parameter names</returns>
vector<string> ParamNames(bool includePrecalcs = false)
{
vector<string> vec;
vec.reserve(m_Params.size());
for (auto& param : m_Params)
if ((includePrecalcs && param.IsPrecalc()) || !param.IsPrecalc())
vec.push_back(param.Name());
return vec;
}
/// <summary>
/// Returns an OpenCL string for the fields in this variation
/// that change during iterations.
/// Note these are different than regular variation parameters,
/// and thus require a completely different solution.
/// </summary>
/// <returns>The OpenCL string for the state variables</returns>
virtual string StateOpenCLString() const override
{
ostringstream os, os2;
os2 << "_" << XformIndexInEmber() << ";";
string index = os2.str();
for (auto& param : m_Params)
if (param.IsState())
os << "\n\treal_t " << param.Name() << index;
return os.str();
}
/// <summary>
/// Returns the number of state variables present for this variation.
/// </summary>
/// <returns>The number of state variables</returns>
virtual size_t StateParamCount() const override
{
size_t count = 0;
for (auto& param : m_Params)
if (param.IsState())
count++;
return count;
}
/// <summary>
/// Initialize the state variables contained in the passed in array.
/// This is meant to be used only with OpenCL to initialize a state struct for every thread before
/// starting iteration.
/// </summary>
/// <param name="t">The pointer to the state variables.</param>
/// <param name="index">The offset in the pointer where the data begins.</param>
virtual void InitStateVars(T* t, size_t& index) override
{
for (auto& param : m_Params)
if (param.IsState())
t[index++] = param.ParamVal();
}
/// <summary>
/// Return the name, weight and parameters of the variation as a string.
/// </summary>
/// <returns>The name, weight and parameters of the variation</returns>
virtual string ToString() const override
{
ostringstream ss;
ss << Variation<T>::ToString() << "\n";
for (auto& param : m_Params) ss << param.ToString() << "\n";
return ss.str();
}
/// <summary>
/// Accessors.
/// </summary>
const ParamWithName<T>* Params() const { return m_Params.data(); }
size_t ParamCount() const { return m_Params.size(); }
const vector<ParamWithName<T>>& ParamsVec() const { return m_Params; }
protected:
/// <summary>
/// Copy the non-precalc parameter values of type U to the pointer locations stored in the params vector of type T,
/// where T is usually the same type as U.
/// This will copy the values to the members of derived classes.
/// </summary>
/// <param name="params">The vector of parameters whose values will be copied</param>
template <typename U>
void CopyParamVals(const vector<ParamWithName<U>>& params)
{
if (m_Params.size() == params.size())
{
for (size_t i = 0; i < m_Params.size(); i++)
if (!m_Params[i].IsPrecalc())
m_Params[i].Set(T(params[i].ParamVal()));
this->Precalc();
}
}
/// <summary>
/// Get a pointer to the underlying ParamWithName object with the specified name.
/// </summary>
/// <param name="name">The name to search for</param>
/// <returns>A pointer to the underlying ParamWithName object if the name matched, else null.</returns>
const ParamWithName<T>* GetUnderlyingParam(const char* name) const
{
for (auto& param : m_Params)
if (!_stricmp(param.Name().c_str(), name))
return &param;
return nullptr;
}
vector<ParamWithName<T>> m_Params;//The params pointer vector which stores pointer to parameter members of derived classes.
};
/// <summary>
/// Macro to define a default copy constructor, a copy constructor for a different template type, and a virtual Copy() function
/// for classes derived directly from Variation.
/// Defining assignment operators isn't really needed because Variations are always held as pointers.
/// </summary>
#ifdef DO_DOUBLE
#define VARCOPYDOUBLE(name) \
virtual void Copy(Variation<double>*& var) const override \
{ \
if (var) \
delete var; \
\
var = new name<double>(*this); \
} \
#else
#define VARCOPYDOUBLE(name)
#endif // DO_DOUBLE
#define VARCOPY(name) \
VARUSINGS \
public: \
name(const name<T>& var) \
: Variation<T>(var) \
{ \
} \
\
template <typename U> \
name(const name<U>& var) \
: Variation<T>(var) \
{ \
} \
\
virtual Variation<T>* Copy() const override \
{ \
return new name<T>(*this); \
} \
\
virtual void Copy(Variation<float>*& var) const override \
{ \
if (var) \
delete var; \
\
var = new name<float>(*this); \
} \
\
VARCOPYDOUBLE(name) \
#define PREPOSTVARCOPY(name, base) \
name(const name<T>& var) \
: base<T>(var) \
{ \
} \
\
template <typename U> \
name(const name<U>& var) \
: base<T>(var) \
{ \
} \
\
virtual Variation<T>* Copy() const override \
{ \
return new name<T>(*this); \
} \
\
virtual void Copy(Variation<float>*& var) const override \
{ \
if (var) \
delete var; \
\
var = new name<float>(*this); \
} \
\
VARCOPYDOUBLE(name) \
/// <summary>
/// Macro to create pre and post counterparts to a variation.
/// Assign type defaults to set.
/// </summary>
#define MAKEPREPOSTVAR(varName, stringName, enumName) MAKEPREPOSTVARASSIGN(varName, stringName, enumName, eVariationAssignType::ASSIGNTYPE_SET)
#define MAKEPREPOSTVARASSIGN(varName, stringName, enumName, assignType) \
template <typename T> \
class EMBER_API Pre##varName##Variation : public varName##Variation<T> \
{ \
VARUSINGS \
public: \
Pre##varName##Variation(T weight = 1.0) : varName##Variation<T>(weight) \
{ \
m_VariationId = eVariationId::VAR_PRE_##enumName; \
m_Name = "pre_"#stringName; \
m_PrePostAssignType = assignType; \
SetType(); \
} \
\
PREPOSTVARCOPY(Pre##varName##Variation, varName##Variation) \
}; \
\
template <typename T> \
class EMBER_API Post##varName##Variation : public varName##Variation<T> \
{ \
VARUSINGS \
public:\
Post##varName##Variation(T weight = 1.0) : varName##Variation<T>(weight) \
{ \
m_VariationId = eVariationId::VAR_POST_##enumName; \
m_Name = "post_"#stringName; \
m_PrePostAssignType = assignType; \
SetType(); \
} \
\
PREPOSTVARCOPY(Post##varName##Variation, varName##Variation) \
};
/// <summary>
/// Macro to define a copy constructor, a copy constructor for a different template type, and a virtual Copy() function
/// for classes derived from ParametricVariation.
/// Another major shortcoming of C++: Ideally, Init() should be a virtual function defined in ParametricVariation.
/// It would be called in that constructor, and defined in each derived class. However, that can't be done because the vtable
/// is not setup during construction.
/// Instead, every class must define it as a non-virtual function and explicitly call it in its constructor.
/// </summary>
#define PARVARUSINGS \
using ParametricVariation<T>::m_Params; \
using ParametricVariation<T>::CopyParamVals;
#define PARVARCOPY(name) \
VARUSINGS \
PARVARUSINGS \
public: \
name(const name<T>& var) \
: ParametricVariation<T>(var) \
{ \
Init(); /* Assign the addresses of the members to the vector. */ \
CopyParamVals(var.ParamsVec()); /* Copy values from var's vector and precalc. */ \
} \
\
template <typename U> \
name(const name<U>& var) \
: ParametricVariation<T>(var) \
{ \
Init(); /* Assign the addresses of the members to the vector. */ \
CopyParamVals(var.ParamsVec()); /* Copy values from var's vector and precalc. */ \
} \
\
virtual Variation<T>* Copy() const override \
{ \
return new name<T>(*this); \
} \
\
virtual void Copy(Variation<float>*& var) const override \
{ \
if (var) \
delete var; \
\
var = new name<float>(*this); \
} \
\
VARCOPYDOUBLE(name) \
#define PREPOSTPARVARCOPY(name, base) \
name(const name<T>& var) \
: base<T>(var) \
{ \
Init(); /* Assign the addresses of the members to the vector. */ \
CopyParamVals(var.ParamsVec()); /* Copy values from var's vector and precalc. */ \
} \
\
template <typename U> \
name(const name<U>& var) \
: base<T>(var) \
{ \
Init(); /* Assign the addresses of the members to the vector. */ \
CopyParamVals(var.ParamsVec()); /* Copy values from var's vector and precalc. */ \
} \
\
virtual Variation<T>* Copy() const override \
{ \
return new name<T>(*this); \
} \
\
virtual void Copy(Variation<float>*& var) const override \
{ \
if (var) \
delete var; \
\
var = new name<float>(*this); \
} \
\
VARCOPYDOUBLE(name)
/// <summary>
/// Macro to create pre and post counterparts to a parametric variation.
/// Assign type defaults to set.
/// This uses the severe hack of calling Init() again after the type has been set
/// avoid having to change the constructor arguments for about 300 variations.
/// </summary>
#define MAKEPREPOSTPARVAR(varName, stringName, enumName) MAKEPREPOSTPARVARASSIGN(varName, stringName, enumName, eVariationAssignType::ASSIGNTYPE_SET)
#define MAKEPREPOSTPARVARASSIGN(varName, stringName, enumName, assignType) \
template <typename T> \
class EMBER_API Pre##varName##Variation : public varName##Variation <T> \
{ \
VARUSINGS \
PARVARUSINGS \
using varName##Variation<T>::Init; \
public:\
Pre##varName##Variation(T weight = 1.0) : varName##Variation<T>(weight) \
{ \
m_VariationId = eVariationId::VAR_PRE_##enumName; \
m_Name = "pre_"#stringName; \
m_PrePostAssignType = assignType; \
SetType(); \
Init(); \
} \
\
PREPOSTPARVARCOPY(Pre##varName##Variation, varName##Variation) \
}; \
\
template <typename T> \
class EMBER_API Post##varName##Variation : public varName##Variation<T> \
{ \
VARUSINGS \
PARVARUSINGS \
using varName##Variation<T>::Init; \
public:\
Post##varName##Variation(T weight = 1.0) : varName##Variation<T>(weight) \
{ \
m_VariationId = eVariationId::VAR_POST_##enumName; \
m_Name = "post_"#stringName; \
m_PrePostAssignType = assignType; \
SetType(); \
Init(); \
} \
\
PREPOSTPARVARCOPY(Post##varName##Variation, varName##Variation) \
};
}