Last active
July 3, 2020 21:00
-
-
Save warchildmd/ed40012486f5561437c9645f7343b466 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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