def grease_pencil_frame_handler(scene, flock: Flock, spirograph: Spirograph, context): frame = scene.frame_current if frame == 0: for i, unit in enumerate(flock.units): gp_layer = init_grease_pencil(gpencil_layer_name="unit_{}".format(i), clear_layer=True) gp_layer.frames.new(0) # When reaching final frame, clear handlers if frame >= context.scene.NUM_FRAMES: bpy.app.handlers.frame_change_pre.clear() elif (frame % context.scene.NUM_FRAMES_CHANGE) == 0: flock.update() spirograph.update() # Update target location target = flock.attractor_obj target.location = spirograph.get_hypotrochoid_loc() target.keyframe_insert("location") flock.attractor_pos = np.array(target.location) for i, unit in enumerate(flock.units): gp_layer = init_grease_pencil(gpencil_layer_name="unit_{}".format(i), clear_layer=False) gp_frame = gp_layer.frames.copy(gp_layer.frames[-1]) gp_frame.frame_number = frame p0 = unit.pos p1 = unit.pos + unit.vel draw_line(gp_frame, p0, p1, i)
def animate_hexagonal_automata(p_freeze, p_melt, nb_frames: 10, material_index=0): nb_rows = 100 nb_cols = 100 automaton = HexagonalAutomaton(nb_rows=nb_rows, nb_cols=nb_cols, p_melt=p_melt, p_freeze=p_freeze) # Set middle cell as the only active one automaton.grid = np.zeros((nb_rows, nb_cols), dtype=np.uint8) automaton.grid[(nb_rows // 2, nb_cols // 2)] = 1 FRAMES_SPACING = 1 bpy.context.scene.frame_start = 0 bpy.context.scene.frame_end = nb_frames * FRAMES_SPACING gp_layer = init_grease_pencil(clear_layer=True) #gp_frame = gp_layer.frames.new(0) z = 0 delete_all() for frame in range(0, nb_frames): if frame % 10 == 0: print("Frame {}".format(frame)) #gp_frame = gp_layer.frames.copy(gp_frame) gp_frame = gp_layer.frames.new(frame * FRAMES_SPACING) # reduce reference size at each new frame size = 1 / (frame + 1) # Hexagonal shape size for grid adjustment hex_size = size * math.cos(math.pi / 6) short_size = size / 2 #z += size/2 z = 0 for row in range(nb_rows): for col in range(nb_cols): if automaton.grid[row, col]: # Calculate row and col position for the current cell # taking into account hexagonal shape and shifting by growth row_pos = (row - nb_rows // 2) * (2 * size - short_size) col_pos = (col - nb_cols // 2) * (2 * hex_size) - hex_size # shift even rows if row % 2 == 0: col_pos += hex_size # Render cell #automata_blender_utils.cube_generator(size, row_pos, col_pos, z) #draw_cube(gp_frame, (row_pos, col_pos, z), size, material_index=material_index) draw_circle(gp_frame, (row_pos, col_pos, z), size, 6, material_index=material_index) automaton.update()
def sketch_rnn_draw(): with open("/tmp/stroke.npy", 'rb') as f: stroke = np.load(f)[0] gp_layer = init_grease_pencil() gp_frame = gp_layer.frames.new(0) gp_stroke = gp_frame.strokes.new() gp_stroke.points.add(count=len(stroke)) for i, point in enumerate(stroke): gp_stroke.points[i].co = point
def animate_1d_automata(rule, nb_frames=10, scale=1., material_index=0): # Init automata automaton_size = nb_frames * 2 automaton = Automaton1D(automaton_size, rule=rule) # Set middle cell as the only active one #automaton.grid = np.zeros(automaton_size, dtype=np.uint8) #automaton.grid[automaton_size // 2] = 1 bpy.context.scene.frame_start = 0 bpy.context.scene.frame_end = nb_frames gpencil_obj_name = "GPencil" gp_layer = init_grease_pencil(clear_layer=True, gpencil_obj_name=gpencil_obj_name) gp_frame = gp_layer.frames.new(0) gpencil = bpy.context.view_layer.objects[gpencil_obj_name] # center on middle cell cell_size = 1 translate_vec = np.array([-(automaton_size / 2), 0, 0]) for frame in range(nb_frames): gp_frame = gp_layer.frames.copy(gp_frame) for i, cell in enumerate(automaton.grid): # maintain pyramid shape (render only if further from the center at least the current frame number) if cell and ((automaton_size // 2 - frame) <= i <= (automaton_size // 2 + frame)): # render cell centers = [ (i, frame, 0), # normal center #(i, frame - 1, automaton_size // 2 - frame), # center down #(i, frame - 1, -(automaton_size // 2) + frame), # center up ] for center in centers: centers_shifted = np.array(center) + translate_vec draw_square(gp_frame, centers_shifted, cell_size, material_index=material_index) #draw_cube(gp_frame, centers_shifted, cell_size, material_index=material_index) automaton.update() # scale automaton size along the growth axis if scale != 1.: gpencil.scale[0] = scale gpencil.select_set(True) bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
def lsystem_params_anim(layer_name='GP_layer'): print("###################################") max_depth = 4 nb_frames = 100 bpy.context.scene.frame_end = nb_frames gp_layer = init_grease_pencil(clear_layer=True, gpencil_layer_name=layer_name) azimuth_adds = np.linspace(-40, 40, nb_frames) inclination_adds = np.linspace(-20, 20, nb_frames) for frame in range(nb_frames): base_systems = [ fractal_plant, fractal_plant_b, fractal_plant_c, fractal_plant_e, stochastic_plant ] base_system = base_systems[np.random.randint(0, len(base_systems))] system = LSystem( axiom=base_system.axiom, constants=base_system.constants, rules=base_system.rules, rules_probs=base_system.rules_probs, render_config={ 'azimuth_add': azimuth_adds[np.random.randint(len(azimuth_adds))], #20., 'inclination_add': inclination_adds[np.random.randint( len(inclination_adds))], #0., }) print("###################") print( f"azimuth_add {system.azimuth_add}, inclination_add {system.inclination_add}" ) for i in range(max_depth): if i % 1 == 0: print(f"Depth {i}") system.rewrite() gp_frame = gp_layer.frames.new(frame) render(system.current_state.copy(), lambda x, y, context: draw(x, y, gp_layer, context), azimuth_add=system.azimuth_add, inclination_add=system.inclination_add, inclination=3.7, pos=(0, 0, 0), line_length=1.)
def lsystem_grid(layer_name='GP_layer'): print("###################################") max_depth = 4 bpy.context.scene.frame_end = 100 SPACING_FACTOR = 20 NB_ROWS = 10 NB_COLS = 8 gp_layer = init_grease_pencil(clear_layer=True, gpencil_layer_name=layer_name) gp_frame = gp_layer.frames.new(0) azimuth_adds = np.linspace(5, 70, NB_ROWS) inclination_adds = np.linspace(-20, 20, NB_COLS) for row in range(NB_ROWS): for col in range(NB_COLS): base_lsystem = LSystem(axiom=['X'], constants=['-', '+', '[', ']'], rules={ 'X': 'F+[[X]-X]-F[-FX]+X', 'F': 'FF', }, render_config={ 'azimuth_add': azimuth_adds[row], 'inclination_add': inclination_adds[col], }) print("###################") print(f"row {row}, col {col}") print( f"azimuth_add {base_lsystem.azimuth_add}, inclination_add {base_lsystem.inclination_add}" ) #print("n={}, alpha={}".format(max_depth, system.render_config['azimuth_add'])) #print("{}".format(system.axiom)) #print("{}".format(system.rules)) for i in range(max_depth): if i % 1 == 0: print(f"Depth {i}") base_lsystem.rewrite() render(base_lsystem.current_state.copy(), lambda x, y, context: draw(x, y, gp_layer, context), azimuth_add=base_lsystem.azimuth_add, inclination_add=base_lsystem.inclination_add, inclination=3.7, pos=(row * SPACING_FACTOR, col * SPACING_FACTOR, 0), line_length=.5)
def animate_2d_automata(rule, nb_frames: 10, use_grease_pencil=True): nb_rows = 10 nb_cols = 10 gol = Automaton2D(nb_rows, nb_cols, rule, seed=11) FRAMES_SPACING = 1 bpy.context.scene.frame_start = 0 bpy.context.scene.frame_end = nb_frames * FRAMES_SPACING if use_grease_pencil: gp_layer = init_grease_pencil(clear_layer=True) else: obj_size = 0.7 subdivisions = 2 scale_factor = 0.2 init_mat_color = (0.7, 0.1, 0.1) # obj_generator = lambda idx: automata_blender_utils.icosphere_generator(obj_size, subdivisions, idx[0], idx[1], 0) obj_generator = lambda idx: automata_blender_utils.cube_generator( obj_size, idx[0], idx[1], 0) obj_updater = lambda obj, grid, idx: automata_blender_utils.object_updater_hide( obj, grid[idx]) # obj_updater = lambda obj, grid, idx: automata_blender_utils.object_updater_scale(obj, grid[idx], # scale_factor=scale_factor) # obj_updater = lambda obj, grid, idx: automata_blender_utils.object_updater_color_vector( # obj, grid[:, idx[0], idx[1]]) delete_all() obj_grid = automata_blender_utils.create_grid(gol, obj_generator) # automata_blender_utils.init_materials(obj_grid, init_mat_color) gol.update() for frame in range(nb_frames): if use_grease_pencil: gp_frame = gp_layer.frames.new(frame * FRAMES_SPACING) for idx, val in np.ndenumerate(gol.grid): if val: draw_square(gp_frame, (idx[0], idx[1], 0), 1) else: bpy.context.scene.frame_set(frame) automata_blender_utils.update_grid(obj_grid, gol, obj_updater) gol.update()
def animate_lsystem(system: LSystem, max_depth: int, pos=(0, 0, 0), layer_name='GP_layer'): gp_layer = init_grease_pencil(clear_layer=True, gpencil_layer_name=layer_name) print("###################") print(f"{layer_name}") print("n={}, alpha={}".format(max_depth, system.render_config['azimuth_add'])) print(system.axiom) print(system.rules) for i in range(max_depth): if i % 1 == 0: print(f"Depth {i}") gp_frame = gp_layer.frames.new(i) system.rewrite() # notice we skip rendering axioms state render(system.current_state.copy(), lambda x, y, context: draw(x, y, gp_layer, context), azimuth_add=system.azimuth_add, inclination_add=system.inclination_add, inclination=4., pos=(0, 0, 0), line_length=1.)