Skip to content

Instantly share code, notes, and snippets.

@helxsz
Last active June 9, 2017 14:26
Show Gist options
  • Select an option

  • Save helxsz/db0fbf4c2a7a6782d61c73377843f63e to your computer and use it in GitHub Desktop.

Select an option

Save helxsz/db0fbf4c2a7a6782d61c73377843f63e to your computer and use it in GitHub Desktop.
blender create many objects
# 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)
#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