Skip to content

Instantly share code, notes, and snippets.

@warchildmd
Last active July 3, 2020 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save warchildmd/ed40012486f5561437c9645f7343b466 to your computer and use it in GitHub Desktop.
Save warchildmd/ed40012486f5561437c9645f7343b466 to your computer and use it in GitHub Desktop.
import bpy
from random import randint
from copy import copy, deepcopy
mat_alive = bpy.data.materials.get("Alive")
# mat_dead = bpy.data.materials.get("Dead")
def hex_to_rgb(hex_value, mult = 1.0):
b = (hex_value & 0xFF) / 255.0
g = ((hex_value >> 8) & 0xFF) / 255.0
r = ((hex_value >> 16) & 0xFF) / 255.0
return r * mult, g * mult, b * mult
def assign_mat_to_object(obj, material, alive):
material.blend_method = 'BLEND'
if alive == 0:
material.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 0.00
material.node_tree.nodes["Principled BSDF"].inputs[17].default_value = (*hex_to_rgb(0xFFC24A), 1)
else:
material.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 1.00
if randint(0, 1) == 0:
material.node_tree.nodes["Principled BSDF"].inputs[17].default_value = (*hex_to_rgb(0x01D4B4, 4.0), 1)
else:
material.node_tree.nodes["Principled BSDF"].inputs[17].default_value = (*hex_to_rgb(0xFF9C00, 8.0), 1)
if obj.data.materials:
pass
# obj.data.materials[0] = material
else:
obj.data.materials.append(material)
def cube_name_by_idx(idx):
if idx == 0:
return 'Cube'
else:
return 'Cube.{:03d}'.format(idx)
def mat_name_by_idx(idx):
if idx == 0:
return 'Alive'
else:
return 'Alive.{:03d}'.format(idx)
def cube_name(i, j, k, grid_size):
idx = i
idx = idx * grid_size + j
idx = idx * grid_size + k
return cube_name_by_idx(idx)
def mat_name(i, j, k, grid_size):
idx = i
idx = idx * grid_size + j
idx = idx * grid_size + k
return mat_name_by_idx(idx)
def calculate_alive_neighbours(grid, i, j, k, grid_size):
alives = 0
for m in [-1, 0, 1]:
for n in [-1, 0, 1]:
for o in [-1, 0, 1]:
# check margins
if i + m < 0 or i + m >= grid_size:
continue
if j + n < 0 or j + n >= grid_size:
continue
if k + o < 0 or k + o >= grid_size:
continue
if m == 0 and n == 0 and o == 0:
continue
if grid[i + m][j + n][k + o] == 1:
alives += 1
return alives
def grid_sum(grid, grid_size):
s = 0
for i in range(grid_size):
for j in range(grid_size):
for k in range(grid_size):
s += grid[i][j][k]
return s
def calculate_next_step(grid, grid_size):
new_grid = deepcopy(grid)
born = 0
died = 0
print(grid_sum(grid, grid_size))
for i in range(grid_size):
for j in range(grid_size):
for k in range(grid_size):
neighbours = calculate_alive_neighbours(grid, i, j, k, grid_size)
if grid[i][j][k] == 0:
if 2 <= neighbours <= 4:
new_grid[i][j][k] = 1
born += 1
else:
if neighbours < 2 or neighbours > 4:
new_grid[i][j][k] = 0
died += 1
print(born, died)
print(grid_sum(new_grid, grid_size))
return new_grid
def draw_board(grid, grid_size):
for i in range(grid_size):
for j in range(grid_size):
for k in range(grid_size):
ob = bpy.data.objects[cube_name(i, j, k, grid_size)]
mat = bpy.data.materials[mat_name(i, j, k, grid_size)]
assign_mat_to_object(ob, mat, grid[i][j][k])
def keyframe_props(grid_size):
for i in range(grid_size):
for j in range(grid_size):
for k in range(grid_size):
mat = bpy.data.materials[mat_name(i, j, k, grid_size)]
mat.node_tree.nodes["Principled BSDF"].inputs[17].keyframe_insert(data_path='default_value')
mat.node_tree.nodes["Principled BSDF"].inputs[18].keyframe_insert(data_path='default_value')
grid_size = 7
current_grid = [[[1 if randint(0, 4) < 1 else 0 for k in range(grid_size)] for j in range(grid_size)] for i in
range(grid_size)]
for i in range(grid_size):
for j in range(grid_size):
for k in range(grid_size):
if mat_name(i, j, k, grid_size) not in bpy.data.materials:
print("Creating material")
mat_alive.copy()
else:
print('Clearing animation')
bpy.data.materials[mat_name(i, j, k, grid_size)].node_tree.animation_data_clear()
bpy.ops.mesh.primitive_cube_add(location=(i * 2.1, j * 2.1, k * 2.1))
print('Created cube ' + cube_name(i, j, k, grid_size))
total_frames = 241
for frame_num in range(0, total_frames, 15):
bpy.context.scene.frame_set(frame_num)
draw_board(current_grid, grid_size)
keyframe_props(grid_size)
if frame_num % 30 == 0:
current_grid = calculate_next_step(current_grid, grid_size)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment