-- ============================================================= -- Linearly interpolate genomes 'A' through genome 'B' and save -- into genome 'C'. -- -- A is the starting genome index -- B is the ending genome index (> A) -- C is the interpolated genome index (> B) -- -- LIN_STEPS is the number of linear interpolation steps -- ROT_STEPS is the number of rotational steps (degrees) -- ROT_LOOPS is the number of rotational loops per genome -- A, B, C = 0, 1, 2 LIN_STEPS = 36 ROT_STEPS = 36 ROT_LOOPS = 1 -- ============================================================= function init_xf(ga) ga.x, ga.y = 0, 0 ga.scale = 100 ga.ax, ga.ay = 0, 0 ga.bx, ga.cy = 1, 1 ga.cx, ga.by = 0, 0 ga.apx, ga.apy = 0, 0 ga.bpx, ga.cpy = 1, 1 ga.cpx, ga.bpy = 0, 0 ga.color, ga.density = 0, 0 ga.default = true end function interp_genomes_to(genomea, genomeb, genomec, t) local ga, gb = {}, {} ga.nxforms = genomea:num_xforms() gb.nxforms = genomeb:num_xforms() for n = 0, (nxf - 1) do init_xf(ga) init_xf(gb) if n < ga.nxforms then local xf = genomea:get_xform(n) ga.ax, ga.ay = xf:a() ga.bx, ga.by = xf:b() ga.cx, ga.cy = xf:c() ga.apx, ga.apy = xf:ap() ga.bpx, ga.bpy = xf:bp() ga.cpx, ga.cpy = xf:cp() ga.density = xf:density() ga.color = xf:color() ga.default = false; end if n < gb.nxforms then local xf = genomeb:get_xform(n) gb.ax, gb.ay = xf:a() gb.bx, gb.by = xf:b() gb.cx, gb.cy = xf:c() gb.apx, gb.apy = xf:ap() gb.bpx, gb.bpy = xf:bp() gb.cpx, gb.cpy = xf:cp() gb.density = xf:density() gb.color = xf:color() gb.default = false; end local xf = genomec:get_xform(n) local x,y x = ga.ax + t * (gb.ax - ga.ax) y = ga.ay + t * (gb.ay - ga.ay) xf:a(x, y) x = ga.bx + t * (gb.bx - ga.bx) y = ga.by + t * (gb.by - ga.by) xf:b(x, y) x = ga.cx + t * (gb.cx - ga.cx) y = ga.cy + t * (gb.cy - ga.cy) xf:c(x, y) x = ga.apx + t * (gb.apx - ga.apx) y = ga.apy + t * (gb.apy - ga.apy) xf:ap(x, y) x = ga.bpx + t * (gb.bpx - ga.bpx) y = ga.bpy + t * (gb.bpy - ga.bpy) xf:bp(x, y) x = ga.cpx + t * (gb.cpx - ga.cpx) y = ga.cpy + t * (gb.cpy - ga.cpy) xf:cp(x, y) for j = 0, NUM_VARS do local va, vb = 0, 0 if ga.default then va = 0 else va = genomea:get_xform(n):var(j) end if gb.default then vb = 0 else vb = genomeb:get_xform(n):var(j) end xf:var(j, va + t * (vb - va)) end xf:color(ga.color + t *(gb.color - ga.color)) xf:density(ga.density + t *(gb.density - ga.density)) end for k = 0, 255 do local ar,ag,ab = genomea:palette(k) local br,bg,bb = genomeb:palette(k) local r = ar + t * (br - ar) local g = ag + t * (bg - ag) local b = ab + t * (bb - ab) genomec:palette(k, r, g, b) end ga.x, ga.y = genomea:center() gb.x, gb.y = genomeb:center() local x = ga.x + t*(gb.x - ga.x) local y = ga.y + t*(gb.y - ga.y) genomec:center(x, y) ga.scale = genomea:scale() gb.scale = genomeb:scale() genomec:scale(ga.scale + t*(gb.scale - ga.scale)) end --- BEGIN --- num_genomes = frame:num_genomes() if A == nil then A = 0 end if B == nil then B = num_genomes - 1 end if C == nil then C = num_genomes - 0 end for n = A, B - 1 do genomeA = frame:get_genome(n) genomeB = frame:get_genome(n+1) frame:copy_genome(n, C) genomeC = frame:get_genome(C) local deg = -360. / ROT_STEPS for k = 0, ROT_STEPS * ROT_LOOPS do for i = 0, genomeC:num_xforms() - 1 do local xf = genomeC:get_xform(i) if xf:symmetry() == 0.0 then xf:rotate(deg, 0, 0); end end frame:render(C) end a_nxf = genomeA:num_xforms() b_nxf = genomeB:num_xforms() nxf = a_nxf if b_nxf > a_nxf then nxf = b_nxf end if nxf > a_nxf then genomeC:add_xform(nxf - a_nxf) end for i = 0, LIN_STEPS do local t = i / LIN_STEPS interp_genomes_to(genomeA, genomeB, genomeC, t) frame:render(C) end frame:del_genome(C) end