lib/glitch3d/bpy/helpers.py in glitch3d-0.2.4.0 vs lib/glitch3d/bpy/helpers.py in glitch3d-0.5.0.0
- old
+ new
@@ -1,299 +1,217 @@
-REFLECTOR_SCALE = random.uniform(5, 8)
-REFLECTOR_STRENGTH = random.uniform(10, 15)
-REFLECTOR_LOCATION_PADDING = random.uniform(10, 12)
-WIREFRAME_THICKNESS = random.uniform(0.0004, 0.002)
-DISPLACEMENT_AMPLITUDE = random.uniform(0.02, 0.1)
-REPLACE_TARGET = str(random.uniform(0, 9))
-REPLACEMENT = str(random.uniform(0, 9))
-ORIGIN = (0,0,2)
-NUMBER_OF_FRAMES = 100
-SCATTER_INTENSITY = 0.015
-ABSORPTION_INTENSITY = 0.25
-DISPLAY_SCALE = (2, 2, 2)
-PRIMITIVES = ['PYRAMID', 'CUBE']
-props = []
-YELLOW = (1, 0.7, 0.1, 1)
-GREY = (0.2, 0.2, 0.2 ,1)
-BLUE = (0.1, 0.1, 0.8, 0.4)
-PINK = (0.8, 0.2, 0.7, 1.0)
-WORDS = string.ascii_lowercase
-RENDER_OUTPUT_PATHS = []
-NORMALS_RENDERING = False #(random.randint(0, 1) == 1)
-MATERIALS_NAMES = []
+import sys, code, random, os, math, bpy, numpy, uuid, mathutils
-def pry():
- code.interact(local=dict(globals(), **locals()))
+def pry(globs=globals(), locs=locals()):
+ import sys
+ code.interact(local=dict(globs, **locs))
sys.exit("Aborting execution")
-def fetch_material(material_name):
- new_material = bpy.data.materials[material_name].copy()
- return new_material
+def chunk_it(seq, num):
+ avg = len(seq) / float(num)
+ out = []
+ last = 0.0
+ while last < len(seq):
+ out.append(seq[int(last):int(last + avg)])
+ last += avg
+ return out
-def apply_displacement(obj):
- subdivide(obj, 6)
+def add_frame(collection, data_paths):
+ for obj in collection:
+ for path in data_paths:
+ obj.keyframe_insert(data_path=path, index=-1)
+
+# Hashmap with proba in values
+def rand_proba(hashmap):
+ return numpy.random.choice(
+ list(hashmap.keys()),
+ 1,
+ p=list(map(lambda x: x/sum(hashmap.values()), hashmap.values()))
+ )[0]
+
+def apply_displacement(obj, height_map_folder, strength = 0.2, subdivisions = 2):
+ subdivide(obj, subdivisions)
subsurf = obj.modifiers.new(name='subsurf', type='SUBSURF')
subsurf.levels = 2
subsurf.render_levels = 2
displace = obj.modifiers.new(name='displace', type='DISPLACE')
new_texture = bpy.data.textures.new(name='texture', type='IMAGE')
- new_texture.image = random_height_map()
+ new_texture.image = random_height_map(height_map_folder, low = True)
displace.texture = new_texture
+ displace.strength = strength
def look_at(obj):
location_camera = CAMERA.matrix_world.to_translation()
location_object = obj.matrix_world.to_translation()
direction = location_object - location_camera
rot_quat = direction.to_track_quat('-Z', 'Y')
CAMERA.rotation_euler = rot_quat.to_euler()
def shoot(filepath):
- print('Camera now at location: ' + camera_location_string(CAMERA) + ' / rotation: ' + camera_rotation_string(CAMERA))
- SCENE.render.filepath = filepath
+ print('Camera now at location: ' + str(CAMERA.location) + ' / rotation: ' + str(CAMERA.rotation_euler))
+ bpy.context.scene.render.filepath = filepath
if animate:
bpy.ops.render.render(animation=animate, write_still=True)
else:
RENDER_OUTPUT_PATHS.append(filepath)
bpy.ops.render.render(write_still=True)
def output_name(model_path, index = 0):
- if animate:
- return './renders/' + os.path.splitext(model_path)[0].split('/')[-1] + '_' + str(index) + '_' + str(datetime.date.today()) + '_' + str(mode) + '.avi'
- else:
- return './renders/' + os.path.splitext(model_path)[0].split('/')[-1] + '_' + str(index) + '_' + str(datetime.date.today()) + '_' + str(mode) + '.png'
+ return './renders/' + os.path.splitext(model_path)[0].split('/')[-1] + '_' + str(index) + '_' + str(datetime.date.today()) + '_' + str(mode) + ('.avi' if animate else '.png')
-def rotate(model_object, index):
- model_object.rotation_euler.z = math.radians(index * (360.0 / shots_number))
-
# RGB 0 -> 1
def rand_color_value():
return random.uniform(0, 255) / 255
-def rand_location():
- return (rand_location_value(), rand_location_value(), rand_location_value())
+def rand_location(boundary):
+ return (random.uniform(-boundary, boundary), random.uniform(-boundary, boundary), random.uniform(-boundary, boundary))
def rand_rotation():
- return (rand_rotation_value(), rand_rotation_value(), rand_rotation_value())
+ return (math.radians(random.uniform(0, 360)), math.radians(random.uniform(0, 360)), math.radians(random.uniform(0, 360)))
-def rand_rotation_value():
- return round(math.radians(random.uniform(0, 60), 10))
-
-def rand_rotation():
- return (random.uniform(0, 20), random.uniform(0, 20), random.uniform(0, 20))
-
-def rand_location_value():
- return round(random.uniform(-4, 4), 10)
-
-def rand_color():
- return random.choice(COLORS)
-
-def rand_scale():
- return round(random.uniform(0, 0.2), 10)
-
-def rand_scale_vector():
- scale = rand_scale()
- return(scale, scale, scale)
-
def unwrap_model(obj):
if obj.name.startswith('Camera') or obj.name.startswith('Text') or obj.name.startswith('Cube'):
return False
- SCENE.objects.active = obj
+ bpy.context.scene.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.uv.unwrap()
bpy.ops.object.mode_set(mode='OBJECT')
-def camera_rotation_string(camera):
- return str(int(camera.rotation_euler.x)) + ' ' + str(int(camera.rotation_euler.y)) + ' ' + str(int(camera.rotation_euler.z))
+#############
+# <materials>
+#############
-def camera_location_string(camera):
- return str(int(camera.location.x)) + ' ' + str(int(camera.location.y)) + ' ' + str(int(camera.location.z))
+# create material and load .osl file from fixtures
+def load_osl_materials(osl_path):
+ for f in os.listdir(osl_path):
+ if f.endswith('.osl'):
+ material = create_cycles_material('osl_' + f[0:-4] + '_', True)
+ script_node = material.node_tree.nodes.new('ShaderNodeScript')
+ material.node_tree.nodes.new('ShaderNodeOutputMaterial')
+ script_node.mode = 'EXTERNAL'
+ script_node.filepath = osl_path + f
+ assign_node_to_output(material, script_node)
+def fetch_material(material_name):
+ new_material = bpy.data.materials[material_name].copy()
+ return new_material
+
def assign_material(obj, material):
flush_materials(obj.data.materials)
if len(obj.data.materials) == 0:
obj.data.materials.append(material)
else:
obj.data.materials[0] = material
return material
+def random_material(materials_list):
+ return fetch_material(random.choice(materials_list))
+
# Returns a new Cycles material with default DiffuseBsdf node linked to output
-def create_cycles_material(name = 'Object Material - ', clean=False):
+def create_cycles_material(name = 'object_material_', clean=False):
material = bpy.data.materials.new(name + str(uuid.uuid1()))
material.use_nodes = True
if clean:
flush_nodes(material)
return material
-def random_texture():
- texture_path = TEXTURE_FOLDER_PATH + random.choice(os.listdir(TEXTURE_FOLDER_PATH))
+def random_texture(texture_folder_path):
+ texture_path = texture_folder_path + random.choice(os.listdir(texture_folder_path))
print("LOADING TEXTURE -> " + texture_path)
return bpy.data.images.load(texture_path)
-def random_height_map():
- path = HEIGHT_MAP_FOLDER_PATH + random.choice(os.listdir(HEIGHT_MAP_FOLDER_PATH))
+def random_height_map(height_map_folder, low = False):
+ if low:
+ path = height_map_folder + 'low.png'
+ else:
+ path = height_map_folder + random.choice(os.listdir(height_map_folder))
print("LOADING HEIGHT MAP -> " + path)
return bpy.data.images.load(path)
-def random_material(blacklist=[]):
- return fetch_material(random.choice(MATERIALS_NAMES))
-
def assign_texture_to_material(material, texture):
assert material.use_nodes == True
texture_node = material.node_tree.nodes.new('ShaderNodeTexImage')
- emission_node = material.node_tree.nodes.new('ShaderNodeEmission')
- material.node_tree.links.new(texture_node.outputs['Color'], emission_node.inputs['Color'])
+ node = material.node_tree.nodes.new('ShaderNodeBsdfGlossy')
+ material.node_tree.links.new(texture_node.outputs['Color'], node.inputs['Color'])
texture_node.image = texture
- assign_node_to_output(material, emission_node)
+ assign_node_to_output(material, node)
def assign_node_to_output(material, new_node):
assert material.use_nodes == True
output_node = material.node_tree.nodes['Material Output']
material.node_tree.links.new(new_node.outputs[0], output_node.inputs['Surface'])
-def mix_nodes(material, node1, node2):
- mix = material.node_tree.nodes.new('ShaderNodeMixShader')
- material.node_tree.links.new(mix.inputs[1], node1.outputs[0])
- material.node_tree.links.new(mix.inputs[2], node2.outputs[0])
- assign_node_to_output(material, mix)
+def make_object_reflector(obj, color, reflector_scale, reflector_strength):
+ obj.scale = (reflector_scale, reflector_scale, reflector_scale)
+ make_object_emitter(obj, color, reflector_strength)
-def make_object_glossy(obj, color = (PINK), roughness = 0.2):
- material = create_cycles_material('Glossy Material - ')
- glossy_node = material.node_tree.nodes.new('ShaderNodeBsdfGlossy')
- glossy_node.inputs[0].default_value = color
- glossy_node.inputs[1].default_value = roughness
- assign_node_to_output(material, glossy_node)
- assign_material(obj, material)
-
-def make_object_reflector(obj):
- obj.scale = (REFLECTOR_SCALE, REFLECTOR_SCALE, REFLECTOR_SCALE)
- make_object_emitter(obj, REFLECTOR_STRENGTH)
-
-def make_texture_object_transparent(obj, color = (1,1,1,0.5), intensity = 0.25):
- material = obj.data.materials[-1]
- emission_node = material.node_tree.nodes['Emission']
- trans = material.node_tree.nodes.new('ShaderNodeBsdfTransparent')
- add = material.node_tree.nodes.new('ShaderNodeMixShader')
- material.node_tree.links.new(emission_node.outputs[0], add.inputs[0])
- material.node_tree.links.new(trans.outputs[0], add.inputs[1])
- material.node_tree.links.new(emission_node.outputs[0], add.inputs[0])
- add.inputs[0].default_value = intensity
- trans.inputs[0].default_value = color
-
-def make_object_transparent(obj):
- material = create_cycles_material('Transparent Material - ')
- trans = material.node_tree.nodes.new('ShaderNodeBsdfTransparent')
- trans.inputs[0].default_value = rand_color()
- assign_node_to_output(material, trans)
- assign_material(obj, material)
-
-def make_object_emitter(obj, emission_strength = 1):
+def make_object_emitter(obj, color, emission_strength = 1):
emissive_material = assign_material(obj, fetch_material('emission'))
emission_node = emissive_material.node_tree.nodes['Emission']
- emission_node.inputs[0].default_value = rand_color()
+ emission_node.inputs[0].default_value = color
emission_node.inputs[1].default_value = emission_strength
return emission_node
def make_object_gradient_fabulous(obj, color1, color2):
material = assign_material(obj, fetch_material('gradient_fabulous'))
- mixer_node = material.node_tree.nodes.new('ShaderNodeMixRGB')
- gradient_node = material.node_tree.nodes.new('ShaderNodeTexGradient')
- gradient_node.gradient_type = 'SPHERICAL'
- bsdf_node = material.node_tree.nodes.new('ShaderNodeBsdfDiffuse')
- material.node_tree.links.new(gradient_node.outputs['Fac'], mixer_node.inputs['Fac'])
- material.node_tree.links.new(mixer_node.outputs[0], bsdf_node.inputs['Color'])
- assign_node_to_output(material, bsdf_node)
+ mixer_node = material.node_tree.nodes['Mix']
mixer_node.inputs['Color1'].default_value = color1
mixer_node.inputs['Color2'].default_value = color2
-def voronoize(obj, scale = 5.0):
- material = obj.data.materials[-1]
- texture_node = material.node_tree.nodes.new('ShaderNodeTexVoronoi')
- material.node_tree.links.new(texture_node.outputs['Color'], material.node_tree.nodes['Glossy BSDF'].inputs['Color'])
- texture_node.coloring = 'CELLS'
- texture_node.inputs[1].default_value = scale
- VORONOIED.append(obj)
-
-def texture_object(obj):
+def texture_object(obj, texture_folder_path):
new_material = create_cycles_material()
- assign_texture_to_material(new_material, random_texture())
+ assign_texture_to_material(new_material, random_texture(texture_folder_path))
assign_material(obj, new_material)
-def duplicate_object(obj):
- new_object = obj.copy()
- new_object.data = obj.data.copy()
- SCENE.objects.link(new_object)
- return new_object
+#############
+# </material>
+#############
-def random_text():
- global WORDS
- return random.choice(WORDS)
-
-def create_mesh(name, verts, faces, location, edges=[]):
- mesh_data = bpy.data.meshes.new("mesh_data")
- mesh_data.from_pydata(verts, edges, faces)
- mesh_data.update()
- obj = bpy.data.objects.new(name, mesh_data)
- obj.location = location
- SCENE.objects.link(obj)
- return obj
-
-def spawn_text():
+def spawn_text(text_file_path, text = None):
identifier = str(uuid.uuid1())
- new_curve = bpy.data.curves.new(type="FONT",name="Curve - " + identifier)
+ new_curve = bpy.data.curves.new(type="FONT",name="text_curve_" + identifier)
new_curve.extrude = 0.11
- new_text = bpy.data.objects.new("Text - " + identifier, new_curve)
- new_text.data.body = random_text()
- SCENE.objects.link(new_text)
+ content = text if text else random_text(text_file_path)
+ new_text = bpy.data.objects.new("text_" + content, new_curve)
+ new_text.data.body = content
+ bpy.context.scene.objects.link(new_text)
return new_text
-def wireframize(obj, emission_strength = 1):
- SCENE.objects.active = obj
+def wireframize(obj, color, emission_strength = 1, thickness = random.uniform(0.0004, 0.001)):
+ bpy.context.scene.objects.active = obj
+ assert obj.type == 'MESH'
obj.modifiers.new(name = 'wireframe', type='WIREFRAME')
- obj.modifiers['wireframe'].thickness = WIREFRAME_THICKNESS
- make_object_emitter(obj, emission_strength)
+ obj.modifiers['wireframe'].thickness = thickness
+ make_object_emitter(obj, color, emission_strength)
return obj
-def shuffle(obj):
- obj.location = rand_location()
- obj.scale = rand_scale_vector()
+# randomize location and rotation of an object
+def shuffle(obj, boundary):
+ obj.location = rand_location(boundary)
obj.rotation_euler = rand_rotation()
-def series(length, function = math.cos):
- return list(map(lambda x: (0, x, function(x)), pitched_array(0.0, length, 0.1)))
-
-def randomize_reflectors_colors():
- for r in bpy.data.groups['Reflectors'].objects:
- r.data.materials[-1].node_tree.nodes['Emission'].inputs[0].default_value = rand_color()
-
def add_object(obj, x, y, z, radius):
- infer_primitive(obj, location=(x, y, z), radius=radius)
- WIREFRAMES.append(last_added_object(obj))
- group_add(obj, last_added_object(obj))
- return last_added_object(obj)
+ new_obj = infer_primitive(obj, location=(x, y, z), radius=radius)
+ bpy.data.groups['neons'].objects.link(new_obj)
+ group_add(obj, new_obj)
+ return new_obj
def infer_primitive(obj, **kwargs):
- if obj == 'CUBE':
+ if obj == 'Cube':
bpy.ops.mesh.primitive_cube_add(radius = kwargs['radius'], location = kwargs['location'])
- elif obj == 'ICO':
+ elif obj == 'Ico':
bpy.ops.mesh.primitive_ico_sphere_add(location = kwargs['location'])
- elif obj == 'CONE':
+ elif obj == 'Cone':
bpy.ops.mesh.primitive_cone_add(location = kwargs['location'], radius1 = kwargs['radius'])
- elif obj == 'PYRAMID':
- build_pyramid(location = kwargs['location'])
- elif obj == 'PLANE':
+ elif obj == 'Pyramid':
+ return build_pyramid(location = kwargs['location'])
+ elif obj == 'Plane':
bpy.ops.mesh.primitive_plane_add(location = kwargs['location'], radius = kwargs['radius'])
+ return bpy.context.object
def group_add(group_name, obj):
bpy.data.groups[group_name.lower().title()].objects.link(obj)
-def last_added_object(object_name_start):
- l = []
- for obj in bpy.data.objects:
- if obj.name.startswith(object_name_start.lower().title()):
- l.append(obj)
- return l[-1]
-
def last_object_group(group_name):
return bpy.data.groups[group_name.lower().title()].objects[-1]
def build_composite_object(obj, size, radius):
res = []
@@ -317,66 +235,44 @@
group_add(obj, new_obj)
res.append(new_obj)
new_obj.location = ((last_object_group(obj).location.x + 2 * radius), y_index, z_index)
return res
-# Displace vertex by random offset
-def displace_vector(vector):
- return mathutils.Vector((vector.x + random.uniform(-DISPLACEMENT_AMPLITUDE, DISPLACEMENT_AMPLITUDE), vector.y + random.uniform(-DISPLACEMENT_AMPLITUDE, DISPLACEMENT_AMPLITUDE), vector.z + random.uniform(-DISPLACEMENT_AMPLITUDE, DISPLACEMENT_AMPLITUDE)))
-
# Replace vertex coordinate everywhere
def find_and_replace(vector, target, replacement):
return mathutils.Vector((float(str(vector.x).replace(target, replacement)), float(str(vector.y).replace(target, replacement)), float(str(vector.z).replace(target, replacement))))
-def glitch(object):
+def glitch(obj):
bpy.ops.object.mode_set(mode='OBJECT')
- assert object.type == 'MESH'
- ints = list(range(10))
- target = str(ints.pop(int(random.uniform(0, len(ints) - 1))))
- replacement = str(ints.pop(int(random.uniform(0, len(ints)))))
- for vertex in object.data.vertices:
- vertex.co = find_and_replace(vertex.co, target, replacement)
+ if obj.type == 'MESH':
+ ints = list(range(10))
+ target = str(ints.pop(int(random.uniform(0, len(ints) - 1))))
+ replacement = str(ints.pop(int(random.uniform(0, len(ints)))))
+ for vertex in obj.data.vertices:
+ vertex.co = find_and_replace(vertex.co, target, replacement)
+ elif obj.type == 'CURVE':
+ for p in obj.data.splines.active.points:
+ max_amplitude = 0.5
+ p.co.z += random.uniform(-max_amplitude, max_amplitude)
+ else:
+ raise TypeError("object cannot be glitched")
-def displace(object):
+def displace(obj, max_amplitude = 0.06):
bpy.ops.object.mode_set(mode='OBJECT')
- assert object.type == 'MESH'
- for vertex in object.data.vertices:
- vertex.co = displace_vector(vertex.co)
+ assert obj.type == 'MESH'
+ for vertex in obj.data.vertices:
+ vertex.co = mathutils.Vector((vertex.co.x + random.uniform(-max_amplitude, max_amplitude), vertex.co.y + random.uniform(-max_amplitude, max_amplitude), vertex.co.z + random.uniform(-max_amplitude, max_amplitude)))
-def subdivide(object, cuts):
- if SCENE.objects.active != object:
- SCENE.objects.active = object
- assert SCENE.objects.active == object
+def subdivide(obj, cuts):
+ if bpy.context.scene.objects.active != obj:
+ bpy.context.scene.objects.active = obj
+ assert bpy.context.scene.objects.active == obj
bpy.ops.object.mode_set(mode='EDIT')
for index in range(0, cuts):
bpy.ops.mesh.subdivide(cuts)
bpy.ops.object.editmode_toggle()
-def clone(obj):
- new_obj = obj.copy()
- new_obj.data = obj.data.copy()
- new_obj.animation_data_clear()
- SCENE.objects.link(new_obj)
- return new_obj
-
-def add_ocean(spatial_size, resolution, depth = 100, scale=(4,4,4)):
- bpy.ops.mesh.primitive_cube_add(location=(0, 0, -0.4),radius=1)
- ocean = last_added_object('CUBE')
- ocean.scale = scale
- ocean.modifiers.new(name='Ocean', type='OCEAN')
- ocean.modifiers["Ocean"].spatial_size = spatial_size
- ocean.modifiers["Ocean"].resolution = resolution
- ocean.modifiers["Ocean"].depth = depth
- make_object_glossy(ocean, rand_color())
- make_object_gradient_fabulous(ocean, rand_color(), rand_color())
- shadow = clone(ocean)
- shadow.location += mathutils.Vector((1,1,-0.4))
- wireframize(shadow)
- shadow.name = 'shadow'
- ocean.name = 'ocean'
- return [ocean, shadow]
-
# Delete current objects
def flush_objects(objs = bpy.data.objects):
for obj in objs:
bpy.data.objects.remove(obj, do_unlink=True)
@@ -393,29 +289,43 @@
def delete_useless_materials():
for mat in bpy.data.materials:
if mat.name.startswith('Material'):
bpy.data.materials.remove(mat, do_unlink=True)
-# Rotate hue to generate palette
+# Rotate hue to generate a somewhat harmonious palette
def adjacent_colors(r, g, b, number):
- angle = (360 / 5) / 360
+ print("Color scheme: adjacent colors")
+ angle = (360 / number) / 360 # angles are in ?
h, l, s = colorsys.rgb_to_hls(r, g, b)
hue_positions = []
for i in range(number):
hue_positions.append(angle * i)
h = [(h + offset) % 1 for offset in hue_positions]
- adjacent = [colorsys.hls_to_rgb(hi, l, s) for hi in h]
+ return [colorsys.hls_to_rgb(hi, l, s) for hi in h]
+
+# Use saturation increments to generate a color ramp palette
+def color_ramp(r, g, b, number):
+ print("Color scheme: color ramp")
+ h, l, s = colorsys.rgb_to_hls(r, g, b)
+ res = []
+ for i in range(number):
+ saturation = ( s + i * random.uniform(-0.1, 0.1))
+ lightness = (l + i * random.uniform(-0.1, 0.1) )
+ hue = (h + i * random.uniform(-0.1, 0.1))
+ res.append(colorsys.hls_to_rgb(h, lightness, saturation))
+ return res
+
+def rand_color_palette(number):
+ function = random.choice([color_ramp, adjacent_colors])
+ res = list(map(lambda x: list(x), function(rand_color_value(), rand_color_value(), rand_color_value(), number)))
# add alpha component
- res = list(map(lambda x: list(x), adjacent))
for i in res:
i.append(1)
+ print("palette: " + str(res))
return res
-def rand_color_palette(number):
- return adjacent_colors(rand_color_value(), rand_color_value(), rand_color_value(), number)
-
-def build_pyramid(width=random.uniform(1,3), length=random.uniform(1,3), height=random.uniform(1,3), location=ORIGIN):
+def build_pyramid(width=random.uniform(1,3), length=random.uniform(1,3), height=random.uniform(1,3), location=(0,0,0)):
verts=[]
faces=[]
verts.append([-(width/2),(length/2),0.0])
verts.append([-(width/2),-(length/2),0.0])
verts.append([(width/2),-(length/2),0.0])
@@ -424,128 +334,190 @@
faces.append([0,1,2,3])
faces.append([0,1,4])
faces.append([1,2,4])
faces.append([2,3,4])
faces.append([3,0,4])
- return create_mesh('Pyramid ' + str(uuid.uuid1()), verts, faces, location)
+ return create_mesh('pyramid_' + str(uuid.uuid1()), verts, faces, location)
-def build_segment(location, function = series, length = 2):
- verts = function(length)
- edges = []
- for v in range(0, (len(verts) - 1)):
- edges.append([v, v+1])
- return create_mesh('Segment ' + str(uuid.uuid1()), verts, [], location, edges)
+# Cuts a model horizontally into sub models like a scanner
+def cut(obj, slices = 10):
+ thiccness = obj.dimensions.z / slices
+ gap = 0.01 * obj.dimensions.z
+ center(obj)
+ print("Slicing " + obj.name + " in " + str(slices) + " parts " + str(thiccness) + " thicc, gap: " + str(gap))
+ base = obj.location.z - (obj.dimensions.z / 2)
+ for i in range(0,slices - 1):
+ dup = duplicate_object(obj)
+ dup.name = 'subcut_' + obj.name + '_' + str(i)
+ bpy.ops.object.select_all(action='DESELECT')
+ bpy.context.scene.objects.active = dup
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.bisect(plane_co=(0,0,base),plane_no=(0,0,1),clear_outer=False,clear_inner=True)
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.bisect(plane_co=(0,0,base + thiccness),plane_no=(0,0,1),clear_outer=True,clear_inner=False)
+ bpy.ops.object.mode_set(mode='OBJECT')
+ base += thiccness
+ dup.location.z += i * gap
+ dup.location.x += random.uniform(-0.2,0.2)
+ dup.location.y += random.uniform(-0.2,0.2)
+ obj.cycles_visibility.camera = False
-def camera_path(pitch = NUMBER_OF_FRAMES):
- res = []
- initial_z = INITIAL_CAMERA_LOCATION[2]
- initial_x = INITIAL_CAMERA_LOCATION[0]
- for y in pitched_array(initial_x, -initial_x, pitch):
- res.append((initial_x, y, math.sin(0.5*y) + 0.5))
- for x in pitched_array(initial_x, -initial_x, pitch):
- res.append((x,-initial_x, math.sin(0.5*x) + 0.5))
- for y in pitched_array(-initial_x, initial_x, pitch):
- res.append((-initial_x, y, math.sin(0.5*y) + 0.5))
- for x in pitched_array(-initial_x, initial_x, pitch):
- res.append((x, initial_x, math.sin(0.5*x) + 0.5))
- return res
+def duplicate_object(obj):
+ print("Cloning -> " + obj.name)
+ new_object = obj.copy()
+ new_object.data = obj.data.copy()
+ new_object.animation_data_clear()
+ new_object.cycles_visibility.camera = True
+ # assign_material(new_object, obj.data.materials[-1])
+ bpy.context.scene.objects.link(new_object)
+ return new_object
-def pitched_array(minimum, maximum, pitch):
- return list(map(lambda x: (minimum + pitch * x), range(int((maximum - minimum) / pitch))))
+def load_random_obj(path):
+ objs = [f for f in os.listdir(path) if f.endswith('.obj') and not f.endswith('_glitched.obj')]
+ bpy.ops.import_scene.obj(filepath = path + random.choice(objs), use_edges=True)
+ return bpy.context.selected_objects[0]
-def still_routine(max_index, index = 1):
- CAMERA.location = CAMERA_PATH[int((len(CAMERA_PATH) / max_index) * index)]
- CAMERA.rotation_euler.y += math.radians(round(random.uniform(-25, +25)))
- randomize_reflectors_colors()
- if OCEAN:
- make_object_glossy(OCEAN[0])
- assign_material(SUBJECT, random_material())
- rotate(SUBJECT, index)
- for ocean in OCEAN:
- ocean.modifiers['Ocean'].random_seed = round(random.uniform(0, 100))
- ocean.modifiers['Ocean'].choppiness += random.uniform(0, 0.3)
- if bpy.data.groups['Lines'].objects:
- for l in bpy.data.groups['Lines'].objects:
- rotation = rand_rotation()
- l.rotation_euler = rotation
- if props:
- for prop in props:
- prop.location = rand_location()
- prop.rotation_euler = rand_rotation()
- if WIREFRAMES:
- for obj in WIREFRAMES:
- obj.location += mathutils.Vector((random.uniform(0,1),random.uniform(0,1),random.uniform(0,1)))
- obj.rotation_euler = rand_rotation()
- if bpy.data.groups['Displays'].objects:
- for display in bpy.data.groups['Displays'].objects:
- display.location = rand_location()
- rotate(display, index)
+def random_text(file_path):
+ lines = open(file_path).readlines()
+ return lines[random.randrange(len(lines))]
-def animation_routine(frame):
- CAMERA.location = CAMERA_PATH[frame]
- look_at(SUBJECT)
- assign_material(SUBJECT, random_material())
- randomize_reflectors_colors()
- displace(SUBJECT)
- for ocean in OCEAN:
- ocean.modifiers['Ocean'].time += 0.5
- if OCEAN:
- make_object_glossy(OCEAN[0])
- for particle_system in bpy.data.particles:
- particle_system.phase_factor_random += 0.01
- SUBJECT.rotation_euler.z += math.radians(1)
- for l in bpy.data.groups['Lines'].objects:
- l.rotation_euler.x += math.radians(1)
- l.rotation_euler.z += math.radians(1)
- if props:
- for prop in props:
- prop.rotation_euler.x += math.radians(5)
- if WIREFRAMES:
- for obj in WIREFRAMES:
- obj.location.z = math.sin(frame)
- obj.rotation_euler.rotate(mathutils.Euler((math.radians(1), math.radians(1), math.radians(1)), 'XYZ'))
- if bpy.data.groups['Displays'].objects:
- for display in bpy.data.groups['Displays'].objects:
- display.rotation_euler.x += math.radians(2)
+def add_faces(obj):
+ vertices = []
+ for v in obj.data.vertices:
+ vertices.append(v.co)
+ new_obj = create_mesh(obj.name, vertices, random_faces(vertices), obj.location)
+ bpy.data.objects.remove(obj, do_unlink=True)
+ return new_obj
-def create_line(name, point_list, thickness = 0.002, location = (0, -10, 0)):
+def random_faces(vertices):
+ faces = []
+ for i in range(int(len(vertices)/100)):
+ target = vertices[random.choice((range(len(vertices))))]
+ if (random.randint(0, 1) == 1):
+ faces.append(((target + 2), int(target / 6), int(target - 1), target))
+ else:
+ faces.append((int(target / 6), int(target - 1), target))
+ return faces
+
+############
+# <geometry>
+############
+
+def center(obj):
+ bpy.context.scene.objects.active = obj
+ bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
+ bpy.ops.object.origin_set(type="ORIGIN_CENTER_OF_MASS")
+ local_bounding_box_center = 0.125 * sum((mathutils.Vector(b) for b in obj.bound_box), mathutils.Vector())
+ obj.location -= local_bounding_box_center
+ return obj
+
+def resize(obj, pace = 0.05, minimum = 3.0, maximum = 8.0):
+ print("Resizing: " + obj.name)
+ assert minimum < maximum
+ obj.scale = (1,1,1)
+ scale_multiplier = max(obj.dimensions) / (maximum - minimum)
+ if max(obj.dimensions) > maximum:
+ init_scale = obj.scale
+ obj.scale = init_scale - init_scale * scale_multiplier # downscale
+ if obj.scale.x < 0:
+ obj.scale = init_scale * scale_multiplier
+ else:
+ obj.scale = obj.scale + obj.scale * scale_multiplier # upscale
+
+def extrude(obj, thickness=0.05):
+ bpy.context.scene.objects.active = obj
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region={"mirror":False}, TRANSFORM_OT_translate={"value":(thickness, 0, 0), "constraint_orientation":'GLOBAL', "mirror":True, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+def create_line(name, point_list, color, thickness = 0.002, location = (0,0,0)):
line_data = bpy.data.curves.new(name=name,type='CURVE')
line_data.dimensions = '3D'
line_data.fill_mode = 'FULL'
+ # line_data.resolution_u = 4
line_data.bevel_depth = thickness
polyline = line_data.splines.new('POLY')
- polyline.points.add(len(point_list)-1)
- for idx in range(len(point_list)):
- polyline.points[idx].co = (point_list[idx])+(1.0,)
- line = bpy.data.objects.new('line' + str(uuid.uuid1()), line_data)
- SCENE.objects.link(line)
+ # polyline = line_data.splines.new('BEZIER')
+ polyline.points.add(len(point_list)-1) # splines.new return already 1 point
+ # polyline.bezier_points.add(len(point_list)-1) # splines.new return already 1 point
+ for idx, coord in enumerate(point_list):
+ x,y,z = coord
+ polyline.points[idx].co = (x, y, z, 1) # add weight
+ # polyline.bezier_points[idx].co = (x, y, z)
+ polyline.order_u = len(polyline.points)-1
+ # polyline.use_endpoint_u = True
+ line = bpy.data.objects.new(name, line_data)
+ bpy.context.scene.objects.link(line)
line.location = location
- make_object_emitter(line, 0.8)
+ make_object_emitter(line, color, 1.1)
return line
-def add_spotlight(location, intensity, radians):
- bpy.ops.object.lamp_add(type='SPOT', radius=1.0, view_align=False, location=location)
- spot = last_added_object('Spot')
- spot.data.node_tree.nodes['Emission'].inputs[1].default_value = intensity
- spot.data.spot_size = radians
- return spot
+def build_segment(location, function, length = 2, pitch = 0.5, name = None):
+ verts = series(length, function, pitch)
+ edges = []
+ for v in range(0, (len(verts) - 1)):
+ edges.append([v, v+1])
+ name = name if name else 'segment_' + str(uuid.uuid1())
+ return create_mesh(name, verts, [], location, edges)
-def make_world_volumetric(world, scatter_intensity = SCATTER_INTENSITY, absorption_intensity = ABSORPTION_INTENSITY):
- assert world.use_nodes == True
- output = world.node_tree.nodes['World Output']
- bg_node = world.node_tree.nodes.new('ShaderNodeBackground')
- absorption_node = world.node_tree.nodes.new('ShaderNodeVolumeAbsorption')
- scatter_node = world.node_tree.nodes.new('ShaderNodeVolumeScatter')
- add_shader = world.node_tree.nodes.new('ShaderNodeAddShader')
- world.node_tree.links.new(add_shader.outputs[0], output.inputs['Volume'])
- world.node_tree.links.new(bg_node.outputs['Background'], output.inputs['Surface'])
- world.node_tree.links.new(scatter_node.outputs[0], add_shader.inputs[0])
- world.node_tree.links.new(absorption_node.outputs[0], add_shader.inputs[1])
- scatter_node.inputs['Density'].default_value = SCATTER_INTENSITY
- absorption_node.inputs['Density'].default_value = ABSORPTION_INTENSITY
- bg_node.inputs[0].default_value = rand_color()
+def series(length, function, pitch):
+ return list(map(lambda x: (0, x, function(x)), pitched_array(0.0, length, pitch)))
-def add_frame(collection = bpy.data.objects, blacklist = set([])):
- for obj in set(collection) - blacklist:
- obj.keyframe_insert(data_path="rotation_euler", index=-1)
- obj.keyframe_insert(data_path="location", index=-1)
- obj.keyframe_insert(data_path="scale", index=-1)
+def pitched_array(minimum, maximum, pitch):
+ return list(map(lambda x: (minimum + pitch * x), range(int((maximum - minimum) / pitch))))
+
+def create_mesh(name, verts, faces, location, edges=[]):
+ mesh_data = bpy.data.meshes.new("mesh_data")
+ faces = faces if len(faces) == 0 else random_faces(verts)
+ mesh_data.from_pydata(verts, edges, faces)
+ mesh_data.update()
+ obj = bpy.data.objects.new(name, mesh_data)
+ obj.location = location
+ bpy.context.scene.objects.link(obj)
+ bpy.context.scene.objects.active = obj
+ center(obj)
+ return obj
+
+def camera_path(frame_number, radius = 5):
+ fx = lambda x: radius * math.cos(x)
+ fy = lambda y: radius * math.sin(y)
+ factor = (2 * math.pi / NUMBER_OF_FRAMES)
+ return list(map( lambda t: (fx(t * factor), fy(t * factor), INITIAL_CAMERA_LOCATION[2]), range(0, NUMBER_OF_FRAMES)))
+
+# Rotate vector
+def rotate_vector(angle, axis, vin):
+ # Assume axis is a unit vector.
+ # Find squares of each axis component.
+ xsq = axis.x * axis.x
+ ysq = axis.y * axis.y
+ zsq = axis.z * axis.z
+ cosa = math.cos(angle)
+ sina = math.sin(angle)
+ complcos = 1.0 - cosa
+ complxy = complcos * axis.x * axis.y
+ complxz = complcos * axis.x * axis.z
+ complyz = complcos * axis.y * axis.z
+ sinx = sina * axis.x
+ siny = sina * axis.y
+ sinz = sina * axis.z
+ # Construct the x-axis (i).
+ ix = complcos * xsq + cosa
+ iy = complxy + sinz
+ iz = complxz - siny
+ # Construct the y-axis (j).
+ jx = complxy - sinz
+ jy = complcos * ysq + cosa
+ jz = complyz + sinx
+ # Construct the z-axis (k).
+ kx = complxz + siny
+ ky = complyz - sinx
+ kz = complcos * zsq + cosa
+ vout = mathutils.Vector((0.0, 0.0, 0.0))
+ vout.x = ix * vin.x + jx * vin.y + kx * vin.z
+ vout.y = iy * vin.x + jy * vin.y + ky * vin.z
+ vout.z = iz * vin.x + jz * vin.y + kz * vin.z
+ return vout
+
+#############
+# </geometry>
+#############
\ No newline at end of file