summaryrefslogtreecommitdiff
path: root/render.py
diff options
context:
space:
mode:
Diffstat (limited to 'render.py')
-rwxr-xr-xrender.py378
1 files changed, 96 insertions, 282 deletions
diff --git a/render.py b/render.py
index 2a4e0d5..3ba0276 100755
--- a/render.py
+++ b/render.py
@@ -1,94 +1,9 @@
#!/usr/bin/env python
-import os
-import sys
-import numpy as np
-import pickle
-import tempfile
-
-import pygame
-from pygame.locals import *
-
-import src
-from camera import *
-from geometry import *
-from transform import *
-from optics import *
-
-import time
-
-from pycuda import autoinit
-from pycuda.compiler import SourceModule
-from pycuda import gpuarray
+from view import *
from pycuda.characterize import sizeof
+import tempfile
-def to_geometry(viewable, bits):
- if isinstance(viewable, Geometry):
- geometry = viewable
- geometry.build(bits)
- elif isinstance(viewable, Solid):
- geometry = Geometry()
- geometry.add_solid(viewable)
- geometry.build(bits)
- elif isinstance(viewable, Mesh):
- geometry = Geometry()
- geometry.add_solid(Solid(viewable, vacuum, vacuum, surface=lambertian_surface))
- geometry.build(bits)
- else:
- raise Exception("can't convert %s to a geometry" % viewable)
-
- return geometry
-
-def box(lower_bound, upper_bound):
- dx, dy, dz = upper_bound - lower_bound
-
- vertices = np.array([lower_bound,
- lower_bound + (dx,0,0),
- lower_bound + (dx,dy,0),
- lower_bound + (0,dy,0),
- lower_bound + (0,0,dz),
- lower_bound + (dx,0,dz),
- lower_bound + (dx,dy,dz),
- lower_bound + (0,dy,dz)])
-
- triangles = np.empty((12,3), dtype=np.int32)
- # bottom
- triangles[0] = (1,3,2)
- triangles[1] = (1,4,3)
- # top
- triangles[2] = (5,7,6)
- triangles[3] = (5,8,7)
- # left
- triangles[4] = (5,1,2)
- triangles[5] = (5,2,6)
- # right
- triangles[6] = (3,4,8)
- triangles[7] = (3,8,7)
- # front
- triangles[8] = (2,3,7)
- triangles[9] = (2,7,6)
- # back
- triangles[10] = (1,5,8)
- triangles[11] = (1,8,4)
-
- triangles -= 1
-
- return Mesh(vertices, triangles)
-
-def bvh_mesh(geometry, layer):
- lower_bounds = geometry.lower_bounds[geometry.layers == layer]
- upper_bounds = geometry.upper_bounds[geometry.layers == layer]
-
- if len(lower_bounds) == 0 or len(upper_bounds) == 0:
- raise Exception('no nodes at layer %i' % layer)
-
- mesh = box(lower_bounds[0], upper_bounds[0])
-
- for lower_bound, upper_bound in zip(lower_bounds, upper_bounds)[1:]:
- mesh += box(lower_bound, upper_bound)
-
- return mesh
-
-def view(viewable, name='', bits=8, load_bvh=False, camera_view=None, make_movie=False):
+def render(viewable, size=(800,600), name='', bits=8, make_movie=False):
"""
Render `viewable` in a pygame window.
@@ -98,209 +13,137 @@ def view(viewable, name='', bits=8, load_bvh=False, camera_view=None, make_movie
- move: shift+click and drag the mouse
"""
- geometry = to_geometry(viewable, bits)
-
- if load_bvh:
- print 'loading bvh...'
- bvhg = []
+ geometry = build(viewable, bits)
- bvhg.append(geometry)
-
- for layer in sorted(np.unique(geometry.layers)):
- print 'building layer %i' % layer
- bvhg.append(to_geometry(bvh_mesh(geometry, layer), bits))
-
- lower_bound = np.array([np.min(geometry.mesh[:][:,:,0]),
- np.min(geometry.mesh[:][:,:,1]),
- np.min(geometry.mesh[:][:,:,2])])
-
- upper_bound = np.array([np.max(geometry.mesh[:][:,:,0]),
- np.max(geometry.mesh[:][:,:,1]),
- np.max(geometry.mesh[:][:,:,2])])
+ lower_bound, upper_bound = geometry.mesh.get_bounds()
scale = np.linalg.norm(upper_bound-lower_bound)
print 'device %s' % autoinit.device.name()
- module = SourceModule(src.kernel, options=['-I' + src.dir],
- no_extern_c=True, cache_dir=False)
- #geometry.load(module, color=True)
+ module = SourceModule(src.kernel, options=['-I' + src.dir], no_extern_c=True, cache_dir=False)
geometry.load(module, color=False)
- #cuda_raytrace = module.get_function('ray_trace')
cuda_build_rgb_lookup = module.get_function('build_rgb_lookup')
cuda_render = module.get_function('render')
cuda_rotate = module.get_function('rotate')
cuda_translate = module.get_function('translate')
pygame.init()
- size = width, height = 800, 600
+ width, height = size
init_rng = module.get_function('init_rng')
- rng_states_gpu = cuda.mem_alloc(len(geometry.mesh.triangles)*sizeof('curandStateXORWOW', '#include <curand_kernel.h>'))
- init_rng(np.int32(len(geometry.mesh.triangles)), rng_states_gpu, np.int32(0), np.int32(0), block=(64,1,1), grid=(len(geometry.mesh.triangles)//64+1,1))
+
+ rng_state_count = max(len(geometry.mesh.triangles), width*height)
+ rng_states_gpu = cuda.mem_alloc(rng_state_count*sizeof('curandStateXORWOW', '#include <curand_kernel.h>'))
+ init_rng(np.int32(rng_state_count), rng_states_gpu, np.int32(0), np.int32(0), block=(64,1,1), grid=(rng_state_count//64+1,1))
diagonal = np.linalg.norm(upper_bound-lower_bound)
- #source_position = [0, diagonal*1.75, (lower_bound[2]+upper_bound[2])/2]
- source_position = [0, 0, upper_bound[2]+5.0]
+
+ source_position = [0, 0, upper_bound[2]+1.0]
source_positions_gpu = gpuarray.empty(len(geometry.mesh.triangles), dtype=gpuarray.vec.float3)
source_positions_gpu.fill(gpuarray.vec.make_float3(*source_position))
source_directions = np.mean(geometry.mesh[:], axis=1) - source_position
- source_directions_float3 = np.empty(source_positions_gpu.size, dtype=gpuarray.vec.float3)
- source_directions_float3['x'] = source_directions[:,0]
- source_directions_float3['y'] = source_directions[:,1]
- source_directions_float3['z'] = source_directions[:,2]
- source_directions_gpu = cuda.to_device(source_directions_float3)
-
- if (len(geometry.mesh.triangles) < source_positions_gpu.size):
- print width*height
- print source_positions_gpu.size
- raise Exception('not enough rng_states')
+ source_directions_gpu = gpuarray.to_gpu(source_directions.astype(np.float32).view(gpuarray.vec.float3))
rgb_lookup_gpu = gpuarray.zeros(source_positions_gpu.size, dtype=gpuarray.vec.float3)
max_steps = 10
- rgb_runs = 1000
+ rgb_runs = 100
+ print 'building rgb lookup.'
cuda_build_rgb_lookup(np.int32(source_positions_gpu.size), rng_states_gpu, source_positions_gpu, source_directions_gpu, np.int32(geometry.node_map.size-1), np.int32(geometry.first_node), rgb_lookup_gpu, np.int32(rgb_runs), np.int32(max_steps), block=(64,1,1), grid=(source_positions_gpu.size//64+1,1))
+ cuda.Context.synchronize()
+ print 'done.'
rgb_lookup = rgb_lookup_gpu.get()
rgb_lookup['x'] /= rgb_runs
rgb_lookup['y'] /= rgb_runs
rgb_lookup['z'] /= rgb_runs
+ rgb_lookup['x'][rgb_lookup['x'] > 1.0] = 1.0
+ rgb_lookup['y'][rgb_lookup['y'] > 1.0] = 1.0
+ rgb_lookup['z'][rgb_lookup['z'] > 1.0] = 1.0
rgb_lookup_gpu = cuda.to_device(rgb_lookup)
+ camera = Camera(size)
- print rgb_lookup
-
-
-
-
-
-
-
-
-
-
-
-
- if camera_view is None:
- camera = Camera(size)
-
- diagonal = np.linalg.norm(upper_bound-lower_bound)
-
- point = np.array([0, diagonal*1.75, (lower_bound[2]+upper_bound[2])/2])
- axis1 = np.array([1,0,0], dtype=np.double)
- axis2 = np.array([0,0,1], dtype=np.double)
-
- camera.position(point)
-
- origins, directions = camera.get_rays()
+ point = np.array([0, diagonal*1.75, (lower_bound[2]+upper_bound[2])/2])
+ axis1 = np.array([1,0,0], dtype=np.double)
+ axis2 = np.array([0,0,1], dtype=np.double)
- origins_float3 = np.empty(origins.shape[0], dtype=gpuarray.vec.float3)
- origins_float3['x'] = origins[:,0]
- origins_float3['y'] = origins[:,1]
- origins_float3['z'] = origins[:,2]
+ camera.position(point)
- directions_float3 = np.empty(directions.shape[0], dtype=gpuarray.vec.float3)
- directions_float3['x'] = directions[:,0]
- directions_float3['y'] = directions[:,1]
- directions_float3['z'] = directions[:,2]
- else:
- f = open(camera_view, 'rb')
- origins_float3 = pickle.load(f)
- directions_float3 = pickle.load(f)
- point = pickle.load(f)
- axis1 = pickle.load(f)
- axis2 = pickle.load(f)
- f.close()
-
- origins_gpu = cuda.to_device(origins_float3)
- directions_gpu = cuda.to_device(directions_float3)
+ origins, directions = camera.get_rays()
- pixels = np.empty(width*height, dtype=np.int32)
- pixels_gpu = cuda.to_device(pixels)
+ origins_gpu = gpuarray.to_gpu(origins.astype(np.float32).view(gpuarray.vec.float3))
+ directions_gpu = gpuarray.to_gpu(directions.astype(np.float32).view(gpuarray.vec.float3))
+ pixels_gpu = gpuarray.zeros(width*height, dtype=np.int32)
nruns = 5
-
-
screen = pygame.display.set_mode(size)
pygame.display.set_caption(name)
-
-
-
-
-
nblocks = 64
- gpu_kwargs = {'block': (nblocks,1,1), 'grid':(pixels.size/nblocks+1,1)}
-
if make_movie:
+ image_index = 0
tempdir = tempfile.mkdtemp()
- def screenshot(dir=''):
- if name == '':
- root, ext = 'screenshot', 'png'
- else:
- root, ext = name, 'png'
-
- filename = os.path.join(dir,'.'.join([root, ext]))
-
- i = 1
- while os.path.exists(filename):
- filename = os.path.join(dir,'.'.join([root + str(i), ext]))
- i += 1
+ def update():
+ """Render the mesh and display to screen."""
- pygame.image.save(screen, filename)
- print 'image saved to %s' % filename
+ global image_index
- def render():
- """Render the mesh and display to screen."""
t0 = time.time()
- cuda_render(np.int32(pixels.size), rng_states_gpu, origins_gpu, directions_gpu, np.int32(geometry.node_map.size-1), np.int32(geometry.first_node), rgb_lookup_gpu, np.int32(nruns), pixels_gpu, np.int32(max_steps), **gpu_kwargs)
+ cuda_render(np.int32(pixels_gpu.size), rng_states_gpu, origins_gpu, directions_gpu, np.int32(geometry.node_map.size-1), np.int32(geometry.first_node), rgb_lookup_gpu, np.int32(nruns), pixels_gpu, np.int32(max_steps), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
cuda.Context.synchronize()
elapsed = time.time() - t0
print 'elapsed %f sec' % elapsed
- cuda.memcpy_dtoh(pixels, pixels_gpu)
- pygame.surfarray.blit_array(screen, pixels.reshape(size))
+ pygame.surfarray.blit_array(screen, pixels_gpu.get().reshape(size))
pygame.display.flip()
- if make_movie:
- screenshot(tempdir)
+ update()
- render()
+ if make_movie:
+ screenshot(screen, name, tempdir, image_index)
+ image_index += 1
done = False
clicked = False
shift = False
- current_layer = 0
-
while not done:
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN:
if event.button == 4:
v = scale*np.cross(axis1,axis2)/10.0
- cuda_translate(np.int32(pixels.size), origins_gpu, gpuarray.vec.make_float3(*v), **gpu_kwargs)
+ cuda_translate(np.int32(pixels_gpu.size), origins_gpu, gpuarray.vec.make_float3(*v), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
point += v
- render()
+ update()
+
+ if make_movie:
+ screenshot(screen, name, tempdir, image_index)
+ image_index += 1
if event.button == 5:
v = -scale*np.cross(axis1,axis2)/10.0
- cuda_translate(np.int32(pixels.size), origins_gpu, gpuarray.vec.make_float3(*v), **gpu_kwargs)
+ cuda_translate(np.int32(pixels_gpu.size), origins_gpu, gpuarray.vec.make_float3(*v), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
point += v
- render()
+ update()
+
+ if make_movie:
+ screenshot(screen, name, tempdir, image_index)
+ image_index += 1
if event.button == 1:
clicked = True
@@ -324,25 +167,34 @@ def view(viewable, name='', bits=8, load_bvh=False, camera_view=None, make_movie
if shift:
v = mouse_direction*scale*length/float(width)
- cuda_translate(np.int32(pixels.size), origins_gpu, gpuarray.vec.make_float3(*v), **gpu_kwargs)
+ cuda_translate(np.int32(pixels_gpu.size), origins_gpu, gpuarray.vec.make_float3(*v), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
point += v
- render()
+ update()
+
+ if make_movie:
+ screenshot(screen, name, tempdir, image_index)
+ image_index += 1
+
else:
phi = np.float32(2*np.pi*length/float(width))
n = rotate(mouse_direction, np.pi/2, \
-np.cross(axis1,axis2))
- cuda_rotate(np.int32(pixels.size), origins_gpu, phi, gpuarray.vec.make_float3(*n), **gpu_kwargs)
+ cuda_rotate(np.int32(pixels_gpu.size), origins_gpu, phi, gpuarray.vec.make_float3(*n), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
- cuda_rotate(np.int32(pixels.size), directions_gpu, phi, gpuarray.vec.make_float3(*n), **gpu_kwargs)
+ cuda_rotate(np.int32(pixels_gpu.size), directions_gpu, phi, gpuarray.vec.make_float3(*n), block=(nblocks,1,1), grid=(pixels_gpu.size//nblocks+1,1))
point = rotate(point, phi, n)
axis1 = rotate(axis1, phi, n)
axis2 = rotate(axis2, phi, n)
- render()
+ update()
+
+ if make_movie:
+ screenshot(screen, name, tempdir, image_index)
+ image_index += 1
if event.type == KEYDOWN:
if event.key == K_LSHIFT or event.key == K_RSHIFT:
@@ -352,71 +204,24 @@ def view(viewable, name='', bits=8, load_bvh=False, camera_view=None, make_movie
done = True
break
- if event.key == K_PAGEUP:
- try:
- if current_layer+1 >= len(bvhg):
- raise IndexError
-
- geometry = bvhg[current_layer+1]
- current_layer += 1
-
- geometry.load(module, color=True)
- render()
- except IndexError:
- print 'no further layers to view'
-
- if event.key == K_PAGEDOWN:
- try:
- if current_layer-1 < 0:
- raise IndexError
-
- geometry = bvhg[current_layer-1]
- current_layer -= 1
-
- geometry.load(module, color=True)
- render()
- except IndexError:
- print 'no further layers to view'
-
- if event.key == K_F11:
- if name == '':
- root, ext = 'camera_view', 'pkl'
- else:
- root, ext = name + '_camera_view', 'pkl'
-
- filename = '.'.join([root, ext])
-
- i = 1
- while os.path.exists(filename):
- filename = '.'.join([root + str(i), ext])
- i += 1
-
- f = open(filename, 'wb')
- cuda.memcpy_dtoh(origins_float3, origins_gpu)
- cuda.memcpy_dtoh(directions_float3, directions_gpu)
- pickle.dump(origins_float3, f)
- pickle.dump(directions_float3, f)
- pickle.dump(point, f)
- pickle.dump(axis1, f)
- pickle.dump(axis2, f)
- f.close()
-
- print 'camera view saved to %s' % filename
-
if event.key == K_F12:
- screenshot()
+ screenshot(screen, name)
if event.type == KEYUP:
if event.key == K_LSHIFT or event.key == K_RSHIFT:
shift = False
+ if event.type == pygame.QUIT:
+ done = True
+ break
+
pygame.display.quit()
if make_movie:
if name == '':
- root, ext = 'movie', 'tgz'
+ root, ext = 'movie', 'avi'
else:
- root, ext = name + '_movie', 'tgz'
+ root, ext = name + '_movie', 'avi'
filename = '.'.join([root, ext])
@@ -426,9 +231,12 @@ def view(viewable, name='', bits=8, load_bvh=False, camera_view=None, make_movie
i += 1
from subprocess import call
- call(['tar', '-czvf', filename, tempdir])
- os.removedirs(tempdir)
+ call(['mencoder', 'mf://' + tempdir + '/*.png', '-mf', 'fps=10', '-o', filename, '-ovc', 'xvid', '-xvidencopts', 'bitrate=3000'])
+
+ import shutil
+
+ shutil.rmtree(tempdir)
if __name__ == '__main__':
import optparse
@@ -437,14 +245,13 @@ if __name__ == '__main__':
import solids
import detectors
+ import scenes
parser = optparse.OptionParser('%prog filename.stl')
parser.add_option('-b', '--bits', type='int', dest='bits',
help='bits for z-ordering space axes', default=8)
- parser.add_option('-l', action='store_true', dest='load_bvh',
- help='load bounding volumes', default=False)
- parser.add_option('-v', '--camera_view', dest='camera_view',
- help='load a camera view', default=None)
+ parser.add_option('-r', '--resolution', dest='resolution',
+ help='specify resolution', default='800,600')
parser.add_option('-m', '--movie', action='store_true', dest='movie',
help='create a movie', default=False)
options, args = parser.parse_args()
@@ -452,17 +259,24 @@ if __name__ == '__main__':
if len(args) < 1:
sys.exit(parser.format_help())
- head, tail = os.path.split(args[0])
- root, ext = os.path.splitext(tail)
+ size = [int(s) for s in options.resolution.split(',')]
+
+ if os.path.exists(args[0]):
+ head, tail = os.path.split(args[0])
+ root, ext = os.path.splitext(tail)
- if ext.lower() == '.stl':
- view(mesh_from_stl(args[0]), root, options.bits, options.load_bvh, options.camera_view, options.movie)
+ if ext.lower() == '.stl':
+ render(mesh_from_stl(args[0]), size, root, options.bits, options.movie)
else:
- import inspect
+ members = dict(inspect.getmembers(detectors) + inspect.getmembers(solids) + inspect.getmembers(scenes))
- members = dict(inspect.getmembers(detectors) + inspect.getmembers(solids))
+ buildable_lookup = {}
+ for member in members.values():
+ if inspect.isfunction(member) and \
+ hasattr(member, 'buildable') and member.buildable == True:
+ buildable_lookup[member.identifier] = member
- if args[0] in members:
- view(members[args[0]], args[0], options.bits, options.load_bvh, options.camera_view, options.movie)
+ if args[0] in buildable_lookup:
+ render(buildable_lookup[args[0]], size, args[0], options.bits, options.movie)
else:
sys.exit("couldn't find object %s" % args[0])