Last active
June 9, 2017 14:26
-
-
Save helxsz/db0fbf4c2a7a6782d61c73377843f63e to your computer and use it in GitHub Desktop.
blender create many objects
This file contains hidden or 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
| # https://blender.stackexchange.com/questions/55965/creating-many-primitive-objects-quickly-with-python | |
| import bpy, random | |
| from random import randint | |
| #Short hands for common calls | |
| scene = bpy.context.scene | |
| selected = bpy.context.selected_objects | |
| mesh = bpy.ops.mesh | |
| context = bpy.context | |
| object = bpy.ops.object | |
| selected_object = bpy.context.active_object | |
| clouds = 500 | |
| def baseObject(x,y,z): | |
| #Creates base cylinder | |
| mesh.primitive_cylinder_add(location=(x,y,z)) | |
| return | |
| def clearScene(): | |
| #Clears the current scene | |
| for selectedObj in bpy.context.scene.objects: | |
| selectedObj.select= True | |
| object.delete() | |
| return | |
| def ObjectCreation(clouds): | |
| for attempts in range(clouds): | |
| x = round(random.uniform(-4.0, 4.0), 10) | |
| y = round(random.uniform(-4.0, 4.0), 10) | |
| z = round(random.uniform(-4.0, 4.0), 10) | |
| baseObject(x,y,z) | |
| context.object.scale[0] = x/10 #X Scale | |
| context.object.scale[1] = y/10 #Y Scale | |
| context.object.scale[2] = z/10 #Z Scale | |
| materialCreation() | |
| print(attempts) | |
| return | |
| def materialCreation(): | |
| #for attempts in range(scale): | |
| randomRed = random.uniform(0.0, 1.0) #Used for random color scale, need to adjust later for color mapping | |
| randomGreen = random.uniform(0.0, 1.0) | |
| randomBlue = random.uniform(0.0, 1.0) | |
| material = bpy.data.materials.new("Material") #Material properties | |
| material.alpha = round(random.uniform(0.1, 1.0), 10) #Opacity | |
| material.use_transparency = True | |
| context.object.show_transparent = True | |
| context.object.data.materials.append(material) #Applies material properties | |
| context.object.color = (randomRed, randomGreen, randomBlue, 1) #Changes objects color(RGB Opacity) | |
| context.object.active_material.use_object_color = True | |
| return | |
| clearScene() | |
| ObjectCreation(clouds) |
This file contains hidden or 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
| #https://blender.stackexchange.com/questions/42217/generate-random-ellipsoids/42232#42232 | |
| import bpy | |
| context = bpy.context | |
| from random import uniform | |
| from mathutils import Vector | |
| count = 200 | |
| # random scale | |
| min_scale = 0.001 | |
| max_scale = 1 | |
| # scale_factor .. scale down to help fit | |
| scale_factor = 0.1 | |
| domain = 1 | |
| only_spheres = True | |
| tries_per_sphere = 256 | |
| use_context_object = False | |
| obj = context.object | |
| def random_vector(a, b): | |
| return Vector([uniform(a, b) for c in "xyz"]) | |
| def checkbounds(sphere, fix): | |
| #return True | |
| loc = sphere.location + fix | |
| #dm = max(sphere.dimensions) / 2 | |
| dm = max(sphere.scale) | |
| _min = -domain + dm | |
| _max = domain - dm | |
| for i, v in enumerate(loc): | |
| if v < _min: | |
| loc[i] = _min | |
| if v > _max: | |
| loc[i] = _max | |
| return loc | |
| def inbounds(sphere, loc): | |
| #return True | |
| dm = max(sphere.scale) | |
| return -domain + dm < min(loc) and max(loc) < domain - dm | |
| def random_sphere(sphere): | |
| # random scale and rotation for sphere based on settings | |
| if only_spheres: | |
| scale = uniform(min_scale , max_scale) * Vector((1, 1, 1)) | |
| else: | |
| scale = random_vector(min_scale, max_scale) | |
| scale = Vector([min(s, domain) for s in scale]) | |
| dom = domain - max(scale) | |
| sphere.scale = scale | |
| sphere.location = random_vector(-dom, dom) | |
| scene = context.scene | |
| mat = bpy.data.materials.get("randobjcol") | |
| if not mat: | |
| mat = bpy.data.materials.new("randobjcol") | |
| mat.use_object_color = True | |
| boundbox = bpy.data.objects.get("BoundBOX") | |
| if not boundbox: | |
| bpy.ops.mesh.primitive_cube_add() | |
| boundbox = context.scene.objects.active | |
| boundbox.name = "BoundBOX" | |
| boundbox.draw_type = 'WIRE' | |
| boundbox.hide_select = True | |
| boundbox.location = (0, 0, 0) | |
| if not scene.objects.get("BoundBOX"): | |
| scene.objects.link(boundbox) | |
| boundbox.scale = domain * Vector((1, 1, 1)) | |
| spheres = [] | |
| if use_context_object and obj: | |
| sphere = obj | |
| else: | |
| bpy.ops.mesh.primitive_uv_sphere_add() | |
| sphere = context.scene.objects.active | |
| bpy.ops.object.shade_smooth() | |
| scene.objects.unlink(sphere) | |
| sphere.active_material = mat | |
| for i in range(count): | |
| spheres.append(sphere) | |
| random_sphere(sphere) | |
| sphere = sphere.copy() | |
| #context.scene.objects.link(sphere) | |
| # update the spheres dimensions | |
| #context.scene.update() | |
| tries = 0 | |
| t_count = 0 | |
| r_count = 0 | |
| moves = 0 | |
| resets = 0 | |
| pfix = Vector() | |
| def within_touch(s1, s2): | |
| def r(s): | |
| return max(s.scale) | |
| #return max(s.dimensions) / 2 | |
| #return sum(s.dimensions) / 3 # average. | |
| d = (s2.location - s1.location) | |
| r1, r2 = r(s1), r(s2) | |
| radsum = r(s1) + r(s2) | |
| if d.length <= 0.0001: | |
| print("SAME") | |
| return Vector((r1, r1, r1)) | |
| # same position | |
| elif d.length < radsum: | |
| # return a vector to move away | |
| d.length = radsum - d.length | |
| return -d | |
| return Vector() | |
| sphere = spheres.pop() | |
| arranged_spheres = [sphere] | |
| sphere = spheres.pop() | |
| while sphere and tries < tries_per_sphere * count: | |
| if t_count > 5 and abs(min_scale - max_scale) > 0.00001: | |
| v = scale_factor * sphere.scale | |
| sphere.scale = Vector([max(s, min_scale) for s in v]) | |
| #scene.update() | |
| touchers = [s for s in [within_touch(sphere, s) for s in arranged_spheres] if s.length > 0] | |
| if len(touchers): | |
| fix = Vector() | |
| for v in touchers: | |
| if sphere.color[0]: | |
| sphere.color[0] -= 0.1 | |
| elif sphere.color[1]: | |
| sphere.color[1] -= 0.01 | |
| else: | |
| sphere.color[2] -= 0.001 | |
| fix += v | |
| #if fix.length < 0.0001 or not inbounds(sphere, loc) or r_count > tries_per_sphere: | |
| if (fix < 0.0001) or r_count > tries_per_sphere / 2: | |
| r_count = 0 | |
| random_sphere(sphere) | |
| resets += 1 | |
| #sphere.color[1] = 0 | |
| else: | |
| loc = checkbounds(sphere, fix) | |
| sphere.location = loc | |
| moves += 1 | |
| t_count += 1 | |
| r_count += 1 | |
| tries += 1 | |
| else: | |
| print("Arranged ", sphere.name, "moves:", moves, "rand moves", resets, "fixes:", t_count) | |
| moves = 0 | |
| t_count = 0 | |
| r_count = 0 | |
| resets = 0 | |
| arranged_spheres.append(sphere) | |
| sphere = spheres.pop() if len(spheres) else None | |
| for s in arranged_spheres: | |
| if not scene.objects.get(s.name): | |
| scene.objects.link(s) | |
| print("Arranged % d of %d" % (len(arranged_spheres), count)) | |
| print("TRIES", tries) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment