2012-04-18 13:21:10 -04:00
|
|
|
#!/usr/bin/env python2
|
2010-08-27 12:28:02 -04:00
|
|
|
#
|
2011-12-17 21:25:15 -05:00
|
|
|
# cuburn, one of a surprisingly large number of ports of the fractal flame
|
2010-08-27 12:28:02 -04:00
|
|
|
# algorithm to NVIDIA GPUs.
|
|
|
|
#
|
2012-02-14 10:40:58 -05:00
|
|
|
# This one is copyright 2010-2012, Steven Robertson <steven@strobe.cc>
|
|
|
|
# and Erik Reckase <e.reckase@gmail.com>.
|
2010-08-27 12:28:02 -04:00
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License version 2 or later
|
|
|
|
# as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
import os
|
|
|
|
import sys
|
2011-10-16 13:51:04 -04:00
|
|
|
import time
|
2011-12-17 21:25:15 -05:00
|
|
|
import json
|
|
|
|
import warnings
|
2011-10-12 14:09:13 -04:00
|
|
|
import argparse
|
2011-06-13 23:20:18 -04:00
|
|
|
from subprocess import Popen
|
2011-10-15 22:22:43 -04:00
|
|
|
from itertools import ifilter
|
2010-08-27 12:28:02 -04:00
|
|
|
|
|
|
|
import numpy as np
|
2011-12-17 21:25:15 -05:00
|
|
|
import pycuda.driver as cuda
|
2011-05-03 17:12:12 -04:00
|
|
|
|
2012-04-16 04:45:34 -04:00
|
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
2012-05-20 16:03:27 -04:00
|
|
|
from cuburn import render, filters, output, profile
|
2012-04-15 01:58:04 -04:00
|
|
|
from cuburn.genome import convert, use, db
|
2011-05-03 13:02:15 -04:00
|
|
|
|
2012-02-14 10:40:58 -05:00
|
|
|
def save(out):
|
|
|
|
# Temporary! TODO: fix this
|
|
|
|
output.PILOutput.save(out.buf, out.idx)
|
|
|
|
print out.idx, out.gpu_time
|
2011-12-17 21:25:15 -05:00
|
|
|
|
|
|
|
def main(args, prof):
|
2012-04-15 02:44:10 -04:00
|
|
|
gdb = db.connect(args.genomedb)
|
2012-05-20 16:00:49 -04:00
|
|
|
gnm, basename = gdb.get_anim(args.flame, args.half)
|
2012-07-05 03:14:44 -04:00
|
|
|
if getattr(args, 'print'):
|
|
|
|
print convert.to_json(gnm)
|
|
|
|
return
|
2012-05-20 16:03:27 -04:00
|
|
|
gprof = profile.wrap(prof, gnm)
|
2011-12-17 21:25:15 -05:00
|
|
|
|
2012-01-03 11:24:20 -05:00
|
|
|
if args.name is not None:
|
|
|
|
basename = args.name
|
|
|
|
prefix = os.path.join(args.dir, basename)
|
2012-07-05 02:05:09 -04:00
|
|
|
if args.subdir:
|
|
|
|
if not os.path.isdir(prefix):
|
|
|
|
os.mkdir(prefix)
|
|
|
|
prefix += '/'
|
|
|
|
else:
|
|
|
|
prefix += '_'
|
2012-01-31 12:14:05 -05:00
|
|
|
frames = [('%s%05d%s.jpg' % (prefix, (i+1), args.suffix), t)
|
2012-05-20 16:03:27 -04:00
|
|
|
for i, t in profile.enumerate_times(gprof)]
|
2011-10-15 22:21:49 -04:00
|
|
|
if args.resume:
|
2012-04-16 04:32:14 -04:00
|
|
|
m = os.path.getmtime(args.flame)
|
2012-01-03 11:24:42 -05:00
|
|
|
frames = (f for f in frames
|
|
|
|
if not os.path.isfile(f[0]) or m > os.path.getmtime(f[0]))
|
|
|
|
|
2012-07-05 03:14:44 -04:00
|
|
|
import pycuda.autoinit
|
2012-05-20 16:03:27 -04:00
|
|
|
rmgr = render.RenderManager()
|
2012-04-10 11:44:25 -04:00
|
|
|
gen = rmgr.render(gnm, gprof, frames)
|
2011-10-12 14:09:13 -04:00
|
|
|
|
2012-02-14 10:40:58 -05:00
|
|
|
if not args.gfx:
|
2011-12-17 21:25:15 -05:00
|
|
|
for out in gen:
|
|
|
|
save(out)
|
2012-02-14 10:40:58 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
import pyglet
|
2012-04-18 11:59:01 -04:00
|
|
|
w, h = gprof.width, gprof.height
|
2012-02-14 10:40:58 -05:00
|
|
|
window = pyglet.window.Window(w, h, vsync=False)
|
|
|
|
image = pyglet.image.CheckerImagePattern().create_image(w, h)
|
|
|
|
label = pyglet.text.Label('Rendering first frame', x=5, y=h-5,
|
|
|
|
width=w, anchor_y='top', font_size=16,
|
|
|
|
bold=True, multiline=True)
|
|
|
|
|
|
|
|
@window.event
|
|
|
|
def on_draw():
|
|
|
|
window.clear()
|
|
|
|
image.texture.blit(0, 0)
|
|
|
|
label.draw()
|
|
|
|
|
|
|
|
@window.event
|
|
|
|
def on_key_press(sym, mod):
|
|
|
|
if sym == pyglet.window.key.Q:
|
|
|
|
pyglet.app.exit()
|
|
|
|
|
|
|
|
@window.event
|
|
|
|
def on_mouse_motion(x, y, dx, dy):
|
|
|
|
pass
|
|
|
|
|
|
|
|
last_time = [time.time()]
|
|
|
|
|
|
|
|
def poll(dt):
|
|
|
|
out = next(gen, False)
|
|
|
|
if out is False:
|
|
|
|
if args.pause:
|
|
|
|
label.text = "Done. ('q' to quit)"
|
|
|
|
#pyglet.clock.unschedule(poll)
|
|
|
|
else:
|
|
|
|
pyglet.app.exit()
|
|
|
|
elif out is not None:
|
|
|
|
real_dt = time.time() - last_time[0]
|
|
|
|
last_time[0] = time.time()
|
|
|
|
save(out)
|
|
|
|
imgbuf = np.uint8(out.buf.flatten() * 255)
|
|
|
|
image.set_data('RGBA', -w*4, imgbuf.tostring())
|
|
|
|
label.text = '%s (%g fps)' % (out.idx, 1./real_dt)
|
|
|
|
else:
|
|
|
|
label.text += '.'
|
|
|
|
|
|
|
|
pyglet.clock.set_fps_limit(30)
|
|
|
|
pyglet.clock.schedule_interval(poll, 1/30.)
|
|
|
|
pyglet.app.run()
|
|
|
|
|
2010-08-27 12:28:02 -04:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2011-10-12 14:09:13 -04:00
|
|
|
parser = argparse.ArgumentParser(description='Render fractal flames.')
|
|
|
|
|
2012-04-15 01:58:04 -04:00
|
|
|
parser.add_argument('flame', metavar='ID', type=str,
|
|
|
|
help="Filename or flame ID of genome to render")
|
2011-10-12 14:09:13 -04:00
|
|
|
parser.add_argument('-g', action='store_true', dest='gfx',
|
|
|
|
help="Show output in OpenGL window")
|
|
|
|
parser.add_argument('-n', metavar='NAME', type=str, dest='name',
|
|
|
|
help="Prefix to use when saving files (default is basename of input)")
|
2012-01-31 12:14:05 -05:00
|
|
|
parser.add_argument('--suffix', metavar='NAME', type=str, dest='suffix',
|
|
|
|
help="Suffix to use when saving files (default '')", default='')
|
2011-10-12 14:09:13 -04:00
|
|
|
parser.add_argument('-o', metavar='DIR', type=str, dest='dir',
|
|
|
|
help="Output directory", default='.')
|
2011-10-15 22:21:49 -04:00
|
|
|
parser.add_argument('--resume', action='store_true', dest='resume',
|
2012-01-03 11:24:42 -05:00
|
|
|
help="Don't overwrite output files that are newer than the input")
|
2012-01-03 12:03:32 -05:00
|
|
|
parser.add_argument('--pause', action='store_true',
|
|
|
|
help="Don't close the preview window after rendering is finished")
|
2012-07-05 02:05:09 -04:00
|
|
|
parser.add_argument('-d', '--genomedb', metavar='PATH', type=str,
|
2012-04-15 01:58:04 -04:00
|
|
|
help="Path to genome database (file or directory, default '.')",
|
|
|
|
default='.')
|
2012-07-05 02:05:09 -04:00
|
|
|
parser.add_argument('--subdir', action='store_true',
|
|
|
|
help="Use basename as subdirectory of out dir, instead of prefix")
|
2012-05-20 16:03:27 -04:00
|
|
|
parser.add_argument('--half', action='store_true',
|
|
|
|
help='Use half-loops when converting nodes to animations')
|
2012-07-05 03:14:44 -04:00
|
|
|
parser.add_argument('--print', action='store_true',
|
|
|
|
help="Print the blended animation and exit.")
|
2012-05-20 16:03:27 -04:00
|
|
|
profile.add_args(parser)
|
2012-04-15 01:58:04 -04:00
|
|
|
|
2011-12-17 21:25:15 -05:00
|
|
|
args = parser.parse_args()
|
2012-05-20 16:03:27 -04:00
|
|
|
pname, prof = profile.get_from_args(args)
|
2011-12-17 21:25:15 -05:00
|
|
|
main(args, prof)
|