From a7900f187db8a7122198b56acac7c5c874fd1c13 Mon Sep 17 00:00:00 2001 From: Steven Robertson Date: Sun, 1 May 2011 09:36:29 -0400 Subject: [PATCH] Add support for variations. --HG-- rename : cuburn/variations.py => cuburn/code/variations.py --- cuburn/code/iter.py | 29 +++++++++++++++++----------- cuburn/code/mwc.py | 1 - cuburn/code/variations.py | 40 +++++++++++++++++++++++++++++++++++++++ cuburn/render.py | 17 +++++++++-------- cuburn/variations.py | 28 --------------------------- main.py | 4 ++-- 6 files changed, 69 insertions(+), 50 deletions(-) create mode 100644 cuburn/code/variations.py delete mode 100644 cuburn/variations.py diff --git a/cuburn/code/iter.py b/cuburn/code/iter.py index 7d519dd..2cbe6cb 100644 --- a/cuburn/code/iter.py +++ b/cuburn/code/iter.py @@ -7,7 +7,7 @@ from pycuda.driver import In, Out, InOut from pycuda.compiler import SourceModule import numpy as np -from cuburn.code import mwc +from cuburn.code import mwc, variations from cuburn.code.util import * import tempita @@ -32,10 +32,18 @@ void apply_xf{{xfid}}(float *ix, float *iy, float *icolor, float tx, ty, ox = *ix, oy = *iy; {{apply_affine('ox', 'oy', 'tx', 'ty', px, 'xf.c', 'pre')}} - // tiny little TODO: variations + ox = 0; + oy = 0; - *ix = tx; - *iy = ty; + {{for v in xform.vars}} + if (1) { + float w = {{px.get('xf.var[%d]' % v)}}; + {{variations.var_code[variations.var_nos[v]]()}} + } + {{endfor}} + + *ix = ox; + *iy = oy; float csp = {{px.get('xf.color_speed')}}; *icolor = *icolor * (1.0f - csp) + {{px.get('xf.color')}} * csp; @@ -64,7 +72,7 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) { float xfsel = mwc_next_01(&rctx); {{for xfid, xform in enumerate(features.xforms)}} - if (xfsel < {{packer.get('cp.norm_density[%d]' % xfid)}}) { + if (xfsel <= {{packer.get('cp.norm_density[%d]' % xfid)}}) { apply_xf{{xfid}}(&x, &y, &color, info); } else {{endfor}} @@ -78,9 +86,9 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) { continue; } - if (x <= -1.0f || x >= 1.0f || y <= -1.0f || y >= 1.0f - || consec_bad < 0) { + nsamps--; + if (x <= -1.0f || x >= 1.0f || y <= -1.0f || y >= 1.0f) { consec_bad++; if (consec_bad > {{features.max_oob}}) { x = mwc_next_11(&rctx); @@ -92,8 +100,8 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) { } // TODO: dither? - int i = ((int)((y + 1.0f) * 256.0f) * 512) - + (int)((x + 1.0f) * 256.0f); + int i = ((int)((y + 1.0f) * 255.0f) * 512) + + (int)((x + 1.0f) * 255.0f); accbuf[i*4] += color < 0.5f ? (1.0f - 2.0f * color) : 0.0f; accbuf[i*4+1] += 1.0f - 2.0f * fabsf(0.5f - color); accbuf[i*4+2] += color > 0.5f ? color * 2.0f - 1.0f : 0.0f; @@ -101,7 +109,6 @@ void iter(mwc_st *msts, const iter_info *infos, float *accbuf, float *denbuf) { denbuf[i] += 1.0f; - nsamps--; } } """) @@ -118,7 +125,7 @@ def silly(features, cp): iter = IterCode(features) code = assemble_code(BaseCode, mwc.MWC, iter, iter.packer) print code - mod = SourceModule(code) + mod = SourceModule(code, options=['-use_fast_math'], keep=True) info = iter.packer.pack(cp=cp) print info diff --git a/cuburn/code/mwc.py b/cuburn/code/mwc.py index 588f801..f0e60ce 100644 --- a/cuburn/code/mwc.py +++ b/cuburn/code/mwc.py @@ -3,7 +3,6 @@ The multiply-with-carry random number generator. """ import numpy as np -import tempita from cuburn.code.util import * diff --git a/cuburn/code/variations.py b/cuburn/code/variations.py new file mode 100644 index 0000000..77f09fc --- /dev/null +++ b/cuburn/code/variations.py @@ -0,0 +1,40 @@ + +var_nos = {} +var_code = {} + +def _var(num, name = None): + def _var1(func): + if name: + namelo = name + else: + namelo = func.__name__ + var_nos[num] = namelo + var_code[namelo] = func + return _var1 + +# Variables note: all functions will have their weights as 'w', +# input variables 'tx' and 'ty', and output 'ox' and 'oy' available +# from the calling context. Each statement will be placed inside brackets, +# to avoid namespace pollution. +@_var(0) +def linear(): + return """ + ox += tx * w; + oy += ty * w; + """ + +@_var(1) +def sinusoidal(): + return """ + ox += w * sin(tx); + oy += w * sin(ty); + """ + +@_var(2) +def spherical(): + return """ + float r2 = w / (tx*tx + ty*ty); + ox += tx * r2; + oy += ty * r2; + """ + diff --git a/cuburn/render.py b/cuburn/render.py index 018590f..7cc8222 100644 --- a/cuburn/render.py +++ b/cuburn/render.py @@ -219,12 +219,11 @@ class Features(object): self.non_box_temporal_filter = genomes[0].temporal_filter_type self.palette_mode = genomes[0].palette_mode and "linear" or "nearest" - xforms = [XForm.parse(cp) for cp in genomes] - assert len(xforms[0]) == len(xforms[-1]), ("genomes must have same " - "number of xforms! (try running through flam3-genome first)") - self.xforms = [XFormFeatures([x[i] for x in xforms], i) - for i in range(len(xforms[0]))] - self.nxforms = len(self.xforms) + assert len(set([len(cp.xforms) for cp in genomes])) == 1, ("genomes " + "must have same number of xforms! (use flam3-genome first)") + self.nxforms = len(genomes[0].xforms) + self.xforms = [XFormFeatures([cp.xforms[i] for cp in genomes], i) + for i in range(self.nxforms)] if any(lambda cp: cp.final_xform_enable): raise NotImplementedError("Final xform") @@ -242,8 +241,10 @@ class XFormFeatures(object): self.id = xform_id any = lambda l: bool(filter(None, map(l, xforms))) self.has_post = any(lambda xf: getattr(xf, 'post', None)) - self.vars = set([n for x in xforms for n in Variations.names - if getattr(x, n, None)]) + self.vars = set() + for x in xforms: + self.vars = ( + self.vars.union(set([i for i, v in enumerate(x.var) if v]))) class Camera(object): """Viewport and exposure.""" diff --git a/cuburn/variations.py b/cuburn/variations.py deleted file mode 100644 index f6b6689..0000000 --- a/cuburn/variations.py +++ /dev/null @@ -1,28 +0,0 @@ - -class Variations(object): - """ - You know it. - """ - # TODO: precalc - - shortname = "variations" - - def __init__(self, features): - self.features = features - - names = [ "linear", "sinusoidal", "spherical", "swirl", "horseshoe", - "polar", "handkerchief", "heart", "disc", "spiral", "hyperbolic", - "diamond", "ex", "julia", "bent", "waves", "fisheye", "popcorn", - "exponential", "power", "cosine", "rings", "fan", "blob", "pdj", - "fan2", "rings2", "eyefish", "bubble", "cylinder", "perspective", - "noise", "julian", "juliascope", "blur", "gaussian_blur", - "radial_blur", "pie", "ngon", "curl", "rectangles", "arch", "tangent", - "square", "rays", "blade", "secant2", "twintrian", "cross", "disc2", - "super_shape", "flower", "conic", "parabola", "bent2", "bipolar", - "boarders", "butterfly", "cell", "cpow", "curve", "edisc", "elliptic", - "escher", "foci", "lazysusan", "loonie", "pre_blur", "modulus", - "oscilloscope", "polar2", "popcorn2", "scry", "separation", "split", - "splits", "stripes", "wedge", "wedge_julia", "wedge_sph", "whorl", - "waves2", "exp", "log", "sin", "cos", "tan", "sec", "csc", "cot", - "sinh", "cosh", "tanh", "sech", "csch", "coth", "auger", "flux", ] - diff --git a/main.py b/main.py index eed759c..a066c7b 100644 --- a/main.py +++ b/main.py @@ -45,8 +45,8 @@ def main(args): bins = np.minimum(bins, 255) bins = bins.astype(np.uint8) - #if '-g' not in args: - # return + if '-g' not in args: + return imgbuf = (accum * 255).astype(np.uint8)