Skip to content

Instantly share code, notes, and snippets.

@mourginakis
Created February 21, 2024 07:53
Show Gist options
  • Save mourginakis/9b9f4a8571165ad979041dbbbda7aa8a to your computer and use it in GitHub Desktop.
Save mourginakis/9b9f4a8571165ad979041dbbbda7aa8a to your computer and use it in GitHub Desktop.
import bpy
from bpy import data as D
import itertools
import numpy as np
from scipy.signal import convolve
import time
import math
## PRELIM
## Installing packages for blender python:
## cd <blender-directory>/3.4/python/
## bin/python3.10 lib/python3.10/ensurepip
## bin/python3.10 -m pip install scipy numpy
np.random.seed(0)
# Create new collection if it does not exist
if 'animatedcubes' not in bpy.data.collections:
targetcollection = D.collections.new("animatedcubes")
bpy.context.scene.collection.children.link(targetcollection)
## END PRELIM
class Lexicon:
boat = \
"""
.....
..O..
.O.O.
..OO.
.....
"""
toad = \
"""
.OOO.
OOO..
.....
"""
R_pentomino = \
"""
.....
..@@.
.@@..
..@..
.....
"""
century = \
"""
..OO.
OOO..
.O...
"""
glider = \
"""
.O.
..O
OOO
"""
gosper_glider_gun = \
"""
........................O................................................
......................O.O................................................
............OO......OO............OO.....................................
...........O...O....OO............OO.....................................
OO........O.....O...OO...................................................
OO........O...O.OO....O.O................................................
..........O.....O.......O................................................
...........O...O.........................................................
............OO...........................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
.........................................................................
"""
pulsar = \
"""
..OOO...OOO..
.............
O....O.O....O
O....O.O....O
O....O.O....O
..OOO...OOO..
.............
..OOO...OOO..
O....O.O....O
O....O.O....O
O....O.O....O
.............
..OOO...OOO..
"""
pinwheel = \
"""
......OO.....
......OO.....
.............
....OOOO.....
OO.O....O....
OO.O..O.O....
...O...OO.OO.
...O.O..O.OO.
....OOOO.....
.............
....OO.......
....OO.......
.............
"""
_64p2h1v0 = \
"""
...............................
.....OOO...............OOO.....
....O...O.............O...O....
...OO....O...........O....OO...
..O.O.OO.OO...OOO...OO.OO.O.O..
.OO.O....O.OO.OOO.OO.O....O.OO.
O....O...O....O.O....O...O....O
............O.....O............
OO.......OO.........OO.......OO
"""
greyship_with_wick = \
"""
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
...............................................................
........................O............O.........................
.......................OOO..........OOO........................
.......................O.OO........OO.O........................
........................OOO........OOO.........................
........................OOO........OOO.........................
........................OOO........OOO.........................
..........................OOOO..OOOO...........................
...........................OOO..OOO............................
...........................OOO..OOO............................
...............................................................
............................O....O.............................
...........................O.O..O.O............................
.........................OO.OOOOOO.OO..........................
.........................OO........OO..........................
.......................O....OOOOOO....O........................
.......................OOOOO..OO..OOOOO........................
.....................O......OO..OO......O......................
.....................OOOOOOO......OOOOOOO......................
...................O........OO..OO........O....................
...................OOOOOOOOO..OO..OOOOOOOOO....................
.................O..........O....O..........O..................
.................OOOOOOOOOOO..OO..OOOOOOOOOOO..................
...............O............OOOOOO............O................
...............OOOOOOOOOOOOO......OOOOOOOOOOOOO................
.............O..............O....O..............O..............
.............OOOOOOOOOOOOOOO......OOOOOOOOOOOOOOO..............
...........O................OOOOOO................O............
...........OOOOOOOOOOOOOOOOO......OOOOOOOOOOOOOOOOO............
.O.......O..................OO..OO..................O.......O..
OOO......OOOOOOOOOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOO......OOO.
O.OO...O....................OOOOOO....................O...OO.O.
.OOO...OOOOOOOOOOOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOO...OOO..
.OOO.O......................OOOOOO......................O.OOO..
.OO..OOOOOOOOOOOOOOOOOOOOOOO..OO..OOOOOOOOOOOOOOOOOOOOOOO..OO..
......O.....................OO..OO.....................O.......
........OOOOOOOOOOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOO.........
......OO....................OO..OO....................OO.......
......OOOOOOOOOOOOOOOOOOOOOO..OO..OOOOOOOOOOOOOOOOOOOOOO.......
.....O..O...................O....O...................O..O......
..........OOOOOOOOOOOOOOOOOO..OO..OOOOOOOOOOOOOOOOOO...........
....OO...O..................OOOOOO..................O...OO.....
..........OOOOOOOOOOOOOOOOOO......OOOOOOOOOOOOOOOOOO...........
..........OO................O....O................OO...........
...........O.OOOOOOOOOOOOOOO......OOOOOOOOOOOOOOO.O............
...........O................OOOOOO................O............
..........O...OOOOOOOOOOOOOO......OOOOOOOOOOOOOO...O...........
...........O.O..............OO..OO..............O.O............
.........OO...OOOOOOOOOOOOOO......OOOOOOOOOOOOOO...OO..........
..............O..............OOOO..............O...............
..............O..OOOOOOOOOOOO.OO.OOOOOOOOOOOO..O...............
...............................................................
.............OO....OOOOOOOOOOO..OOOOOOOOOOO....OO..............
...............O..O........................O..O................
..............O....OOOOOOOO........OOOOOOOO....O...............
..................OO.......OO....OO.......OO...................
................OO..O.OOOO..........OOOO.O..OO.................
................OO.O........OOOOOO........O.OO.................
.................OOOO..OO...OOOOOO...OO..OOOO..................
..................O.O...O...OO..OO...O...O.O...................
..................OO.O...O..........O...O.OO...................
.....................O...O..........O...O......................
.................O...OO.O............O.OO...O..................
..................OOOO..O...O....O...O..OOOO...................
........................O...O....O...O.........................
........................O............O.........................
.........................O.O......O.O..........................
"""
hivenudger2 = \
"""
.....................O.O...................
....................O..O...................
...................OO......................
..................O...O....................
.................OOO.O.....................
..............OO...........................
.............O...OOOOO.......OOOO.....O..O.
............O...O............O...O...O.....
............O.....OO.........O.......O...O.
............OOO...OOOO........O..O...OOOO..
.............O.......O.....................
.............OO...................OO.......
.............O.O..................OO.......
.............OO..OO.O........O.O..OO.......
..............O.OOO.O...O.OOOO.O..OO.......
.....................OO.O.OO..O...OO...OOO.
................OOOOOO.OO...OOOO..OO...OOO.
.................O....OOO......O..OO...OOO.
..................OO.....OO..OO...OO.......
...................O..O.....OOOO..OO.......
....................O.O.OO.....O..OO.......
..................................OO.......
...........................................
..............................O..O...OOOO..
.............................O.......O...O.
.............................O...O...O.....
.............................OOOO.....O..O.
"""
@staticmethod
def matrix2str(m):
def row2str(row):
return ''.join(str(i) for i in row) + "\n"
s = ''.join([row2str(row) for row in m])
s = s.replace('0', '.')
s = s.replace('1', '@')
return s
@staticmethod
def str_to_matrix(s):
"""Interpret string data from lexicon into a matrix"""
return np.array([[0 if c=='.' else 1 for c in row]
for row in s.split()], dtype=np.uint8)
class GameOfLife:
"""
1. Any live cell with two or three neighbors survives
2. Any dead cell with three live neighbors becomes a live cell
3. All other live cells die in next generation, all dead cells stay dead
Convolution logic adapted from mikelane on github
"""
default_grid_size = 10
kernel = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]], dtype=np.uint8)
def __init__(self, grid_size=default_grid_size):
self.i = 0
self.grid_size = grid_size
self.grid_last = self.make_zeros(self.grid_size)
self.grid = self.make_zeros(self.grid_size)
self.grid_next = self.calculate_next()
def make_soup(self, n):
return np.random.randint(2, size=(n, n), dtype=np.uint8)
def make_zeros(self, n):
return np.zeros((n, n), dtype=np.uint8)
def superimpose(self, pattern):
"""Draw a pattern (np matrix) on top of a matrix of zeros"""
# m (down/row), n (across/columns)
m, n = pattern.shape
m1, n1 = self.grid.shape
# find the indexes of a 'pattern' sized block in the middle
b1, b2 = (m1//2 - m//2), (m1//2 + m//2 + 1)
v1, v2 = (n1//2 - n//2), (n1//2 + n//2 + 1)
self.grid[b1:b2, v1:v2] = pattern
self.grid_next = self.calculate_next()
def calculate_next(self):
C = convolve(self.grid, GameOfLife.kernel, mode='same')
next_grid = (
((self.grid == 1) & (C > 1) & (C < 4))
| ((self.grid == 0) & (C == 3))
).astype(np.uint8)
return next_grid
def tick(self):
self.grid_last = self.grid
self.grid = self.grid_next
self.grid_next = self.calculate_next()
self.i += 1
def get_tiles_that_did_change(self):
return self.grid_last ^ self.grid
def get_tiles_that_will_change(self):
# returns an np.matrix where 0 means the next square stays the same, 1 means it changes
# be careful here: both arrays are uint8, so you'll get an integer overflow
return self.grid ^ self.grid_next
def __str__(self):
"""Pretty print the grid"""
return Lexicon.matrix2str(self.grid)
###################################################
### State Mutating Functions
## LightCubes
def make_lightcube(location):
"""2m x 2m x 2m Cube"""
x, y, z = location
desiredname = f'cube#{x}.{y}'
if desiredname in D.collections['animatedcubes'].objects:
raise Exception(f'This cube {desiredname} already exists')
cube = D.objects['cube' ].copy()
inner = D.objects['inner' ].copy()
arealight = D.objects['arealight'].copy()
inner.parent = cube
arealight.parent = cube
D.collections['animatedcubes'].objects.link(cube)
D.collections['animatedcubes'].objects.link(inner)
D.collections['animatedcubes'].objects.link(arealight)
cube.location = location
cube.hide_render = False
inner.hide_render = False
arealight.hide_render = False
inner.hide_viewport = True # better fps during preview
arealight.hide_viewport = True # better fps during preview
cube.name = desiredname
return desiredname
def set_state_lightcube(name, state):
assert state == 1 or state == 0
assert name.startswith('cube#')
cube = bpy.data.collections['animatedcubes'].objects[name]
x, y, z = cube.location
z = 2 * state # 2 or 0
cube.location = (x, y, z)
def draw_keyframe_lightcube(name, frame):
assert name.startswith('cube#')
cube = bpy.data.collections['animatedcubes'].objects[name]
cube.keyframe_insert(data_path = 'location', frame=frame)
for fcurve in cube.animation_data.action.fcurves:
kf = fcurve.keyframe_points[-1]
kf.interpolation = 'EXPO'
def delete_keyframes_lightcube(name):
assert name.startswith('cube#')
cube = bpy.data.collections['animatedcubes'].objects[name]
if cube.animation_data is not None:
cube.animation_data_clear()
## Backdrop
def reset_backdrop(length):
"""Reset the backdrop to be a bowl that has a square hole in the bottom the (width,length) of length (meters)"""
# Wow, what an absolute challenge to get the backdrop working properly, especially
# since the rest of this project is done programmatically. The problem is that the backdrop
# Needs to be hollow on the bottom to let light through and give the depth illusion.
# Here's the best way I found:
# 1. Create a 'subtraction buffer' cube in the length width and height of all the tiles
# 2. Create a 'bowl' shape: essentially a cylinder with one face removed
# 3. Bevel this 'bowl' so that it's round on the bottom and shade autosmooth
# 4. Boolean subtract the subtraction buffer from the bowl, except for some reason
# union is the operation for difference, not difference, weird and annoying.
# Must have to do with the fact that the geometry has no thickness.
max_x, max_y = length, length
RE_BEVEL = False
if RE_BEVEL == True:
# BE CAREFUL! OVERWRITES DATA EVERY TIME!
try: D.objects.remove(D.objects['backdrop'], do_unlink=True)
except KeyError: pass
newbackdrop = D.objects['backdrop.backup'].copy()
newbackdrop.data = D.objects['backdrop.backup'].data
newbackdrop.name = 'backdrop'
newbackdrop.hide_render = False
D.collections['background'].objects.link(newbackdrop)
import bpy
def apply_transformations_with_context(obj):
# 1. Store the original active object and selection
original_active_object = bpy.context.view_layer.objects.active
original_selected_objects = bpy.context.selected_objects.copy()
# 2. Deselect all objects
bpy.ops.object.select_all(action='DESELECT')
# 3. Select and set the object as active
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
# 4. Apply the transformations (in this example, only the scale)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
# 5. Restore the original selection and active object
for original_obj in original_selected_objects:
original_obj.select_set(True)
bpy.context.view_layer.objects.active = original_active_object
buffer_size = 3000 + max_x # at least twice as big, plus some extra space
# weird bug, dimension change must be called multiple times to close in on target Z value.
# do the transformations need to be applied???
for _ in range(10):
# So apparently you need to set the transformations before you change the data. That's
# why we were running into that weird bug. We probably don't need this for loop anymore,
# but I"m going to keep it because it doesn't add much compute time and my sanity is failing.
apply_transformations_with_context(D.objects['backdrop'])
apply_transformations_with_context(D.objects['bufferminus'])
D.objects['backdrop'].dimensions = (max_x + buffer_size, max_y + buffer_size, buffer_size / 2)
if length == 80*2:
D.objects['backdrop'].location = (0, 0, -1.776) # when board is 80
elif length == 120*2:
D.objects['backdrop'].location = (0, 0, -1.84) # when board is 120
else:
raise NotImplementedError
D.objects['bufferminus'].dimensions = (max_x, max_y, 18.0)
D.objects['bufferminus'].location = (0, 0, 0) #(max_x / 2 - 1, max_y / 2 -1, 0)
## CubeBoard
def make_cubeboard(grid_size):
start = time.time()
names = []
dummy_gameoflife = GameOfLife(grid_size)
for index, z in np.ndenumerate(dummy_gameoflife.grid):
x, y = index
normalized_position = ((x-grid_size/2)*2+1, (y-grid_size/2)*2+1, 0)
name = make_lightcube(normalized_position)
names.append(name)
assert len(names) == grid_size ** 2
end = time.time()
print(f'Execute fn> make_cubeboard: {end-start}s', flush=True)
return names
def delete_cubeboard():
# Flush any preexisting objects from collection
start = time.time()
# Fast method, deleting in a standarf for loop takes literal hours.
scene = bpy.data.scenes['Scene']
collection = bpy.data.collections['animatedcubes']
scene.collection.children.unlink(collection)
bpy.data.collections.remove(collection)
targetcollection = D.collections.new("animatedcubes")
bpy.context.scene.collection.children.link(targetcollection)
# this deletes orphaned data
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
end = time.time()
print(f'Execute fn> delete_cubeboard: {end-start}s', flush=True)
def delete_keyframes_cubeboard():
start = time.time()
for obj in bpy.data.collections.get('animatedcubes').objects:
if obj.name.startswith('cube#'):
delete_keyframes_lightcube(obj.name)
end = time.time()
print(f'Execute fn> delete_keyframes_cubeboard: {end-start}s')
def draw_keyframes_cubeboard(pattern=Lexicon.toad, total_frames=30, speed=0.15):
"""sets all keyframes in the board for a specific pattern in the Lexicon"""
start = time.time()
# auto determine grid size
cubes = [obj for obj in bpy.data.collections.get('animatedcubes').objects if obj.name.startswith('cube#')]
number_of_cubes = len(cubes)
assert math.sqrt(number_of_cubes)**2 == number_of_cubes
grid_size = int(math.sqrt(number_of_cubes))
# Create game of life simulation
game = GameOfLife(grid_size)
frame_begin = 0
frame_step = int(1.0 / speed)
frame_end = total_frames + 1
game.superimpose(Lexicon.str_to_matrix(pattern))
def _draw_keyframes_single_frame(frame_number):
# only updates keyframes for tiles that will change to save compute
def _draw(index):
x, y = index
z = game.grid[x, y]
targetcube_name = f'cube#{(x-grid_size/2)*2+1}.{(y-grid_size/2)*2+1}'
set_state_lightcube(targetcube_name, z)
draw_keyframe_lightcube(targetcube_name, frame_number)
for index, c in np.ndenumerate(game.get_tiles_that_did_change()):
if c == 1:
_draw(index)
for index, c, in np.ndenumerate(game.get_tiles_that_will_change()):
if c == 1:
_draw(index)
# set initial states
for index, z in np.ndenumerate(game.grid):
x, y = index
targetcube_name = f'cube#{(x-grid_size/2)*2+1}.{(y-grid_size/2)*2+1}'
set_state_lightcube(targetcube_name, z)
# draw initial keyframes
_draw_keyframes_single_frame(frame_begin)
for frame_num in range(frame_begin+frame_step, frame_end, frame_step):
print(f'{frame_num}/{total_frames}. ', end='', flush=True)
game.tick()
# print(f'did change: {Lexicon.matrix2str(game.get_tiles_that_did_change())}')
# print(f'{game.i}: {str(game)}')
# print(f'will change: {Lexicon.matrix2str(game.get_tiles_that_will_change())}')
_draw_keyframes_single_frame(frame_num)
end = time.time()
print(f'\nExecute fn> draw_keyframes_cubeboard: {end-start}s')
## Main Script
print('\nStarting Script...')
## Example code for how to make a custom sized grid: (O(n^2)
# board reset for size 80: ~13s
# board reset for size 100: ~35s
# board reset for size 120: ~80s
# grid_size = 120
# delete_cubeboard()
# reset_backdrop(grid_size*2)
# make_cubeboard(grid_size)
def render_toad(frames=390, reset=False):
"""complete"""
# Name: Toad
# Class: Oscillator
# Lifespan: Indefinite
# Discovered by: Simon Norton, 1970
# URL: conwaylife.com/wiki/toad
if reset:
grid_size = 80
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['toadcam']
total_frames = frames # set frames to something else for benchmarking
bpy.data.scenes['Scene'].frame_start = 0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.toad, total_frames=total_frames, speed=0.09)
def render_gosper_glider_gun(reset=False):
"""incomplete"""
# Name: Glider
# Class: Spaceship
# Discovered by: Richard K. Guy, 1969
# URL: conwaylife.com/wiki/Glider
# -----
# Name: Gosper Glider Gun
# Class: Gun
# Discovered by: Bill Gosper, 1970
# URL: conwaylife.com/wiki/Gosper_glider_gun
if reset:
grid_size = 120
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['gliderguncam']
total_frames = 1600+900 # 900/30fps = 36.6s
bpy.data.scenes['Scene'].frame_start = 1600 # 1600 is when it gets close to the edge
bpy.data.scenes["Scene"].frame_end=total_frames # Real render time: 1100 Frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.gosper_glider_gun, total_frames=total_frames, speed=0.14)
def render_century(reset=False):
"""complete"""
# Name: Century
# Class: Hexomino
# Discovered by: Unknown
# Lifespan: 103 Generations
# URL: conwaylife.com/wiki/century
if reset:
grid_size = 80
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['centurycam']
total_frames = 400 # Reaches steady state at ~330
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.century, total_frames=total_frames, speed=0.3)
def render_rpentomino(reset=False):
"""complete"""
# Name: R-pentomino
# Class: Methuselah
# Lifespan: 1103 Generations
# Discovered by: John Conway, 1969
# URL: not set
if reset:
grid_size = 120
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['pentominocam']
total_frames = 600
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.R_pentomino, total_frames=total_frames, speed=0.3)
def render_pulsar(reset=False):
"""complete"""
# Name: Pulsar
# Class: Oscillator
# Discovered by: John Conway, 1970
# Lifespan: Indefinite
if reset:
grid_size = 80
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['pulsarcam']
total_frames = 300
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.pulsar, total_frames=total_frames, speed=0.09)
def render_pinwheel(reset=False):
"""complete"""
# Name: Pinwheel
# Class: Oscillator
# Lifespan: Indefinite
# Discoverd by: Simon Norton, 1970
# URL: conwaylife.com/wiki/Pinwheel
if reset:
grid_size = 80
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['pinwheelcam']
total_frames = 460
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.pinwheel, total_frames=total_frames, speed=0.14)
def render_64P2H1V0(reset=False):
"""complete"""
# Name: 64P2H1V0
# Class: Spaceship
# Lifespan: Indefinite
# Discovered by: Dean Hickerson, 1989
# URL: conwaylife.com/wiki/64P2H1V0
if reset:
grid_size = 80
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['p2cam']
total_frames = 400
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon._64p2h1v0, total_frames=total_frames, speed=0.14)
def render_greyship_with_wick(reset=False):
"""complete"""
# Name: Greyship with wick
# Class: Greyship
# Lifespan: Indefinite
# URL: conwaylife.com/wiki/Greyship
# Discovered by: Hartmut Holzwart, 2005
if reset:
grid_size = 120
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['greyshipwickcam']
total_frames = 490
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.greyship_with_wick, total_frames=total_frames, speed=0.14)
def render_hivenudger2(reset=False):
"""complete"""
# Name: Hivenudger 2
# Class: Puffer
# URL: conwaylife.com/wiki/Hivenudger_2
# Discovered by: Hartmut Holzwart, 1992
if reset:
grid_size = 80
delete_cubeboard()
reset_backdrop(grid_size*2)
make_cubeboard(grid_size)
# - - - - - - - - - - - - - -
bpy.data.scenes['Scene'].camera = bpy.data.objects['hivenudger2cam']
total_frames = 400
bpy.data.scenes['Scene'].frame_start=0
bpy.data.scenes["Scene"].frame_end=total_frames
delete_keyframes_cubeboard()
draw_keyframes_cubeboard(pattern=Lexicon.hivenudger2, total_frames=total_frames, speed=0.14)
#render_toad(reset=True) # size=80 # frames=390
#render_gosper_glider_gun(reset=True) # size=120 # frames=1100
#render_century(reset=True) # size=80 # frames=400
#render_rpentomino(reset=True) # size=120 # frames=600
#render_pulsar(reset=True) # size=80 # frames=300
#render_pinwheel(reset=True) # size=80 # frames=400
render_64P2H1V0(reset=True) # size=80 # frames=400
#render_greyship_with_wick(reset=True) # size=120 # frames=490
#render_hivenudger2(reset=True) # size=80 # frames=400
print('Ended Script. Viewport make take another 30 seconds to buffer new data.')
##########################################################################################
### EVERYTHING BELOW HERE IS UNFINISHED
###
### Timesscales:
### - 150frames/30fps = 5s
### - 300frames/30fps = 10s
### - 600frames/30fps = 20s
### - 900frames/30fps = 30s
###
###
# render at 30fps: 1s=30f; 2s=60f; 3s=90f; 4s=120f
# conwaylife.com/wiki/Glossary_of_basic_terms
def render_glider():
"""incomplete"""
# Name: Glider
# Class: Spaceship
# Discovered by Richard K. Guy, 1969
# URL: conwaylife.com/wiki/Glider
total_frames = 80
bpy.data.scenes["Scene"].frame_end=total_frames
# CreateDisplay(size=40, frames=total_frames, cells=Lexicon.glider)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment