Skip to content

Instantly share code, notes, and snippets.

@Airyzz
Created September 5, 2020 06:42
Show Gist options
  • Save Airyzz/4dfd3b9e70e9d873f527b89e56a10c34 to your computer and use it in GitHub Desktop.
Save Airyzz/4dfd3b9e70e9d873f527b89e56a10c34 to your computer and use it in GitHub Desktop.
Blender Sphere Packing Generator
import bpy
from mathutils import *
import random
rad = 5
numSpheres = 5000
resolution = 0.1
spheres = list()
def dist(point1, point2):
return (point2 - point1).length
class sphere:
pos = 0
r = 0
#create a new sphere
def __init__(self):
self.pos = Vector((
random.uniform(-rad, rad),
random.uniform(-rad, rad),
random.uniform(-rad, rad)
))
#keep trying random locations until the sphere fits
while(self.canMove() == False):
self.pos = Vector((
random.uniform(-rad, rad),
random.uniform(-rad, rad),
random.uniform(-rad, rad)))
#increase the sphere size by the resolution
def grow(self):
self.r += resolution
#check if the sphere collides with the edges (for sphere bounds)
def edges(self):
distance = dist(self.pos, Vector((0,0,0)))
if(distance + self.r >= rad):
return True
def edges_cube(self):
for i in range(3):
if self.pos[i] + self.r > rad or self.pos[i] - self.r < -rad:
return True
return False
#used to check is sphere collides with another sphere
def colliding(self, sphere):
if self == sphere:
return False
return dist(self.pos, sphere.pos) < self.r + sphere.r
#check if the sphere is free to grow
def canMove(self):
for sphere in spheres:
if self.colliding(sphere) or self.edges_cube():
return False
return True
#check if every sphere has collided with either another sphere ot the edges
def allSpheresCollided():
for sphere in spheres:
if sphere.canMove():
return False
return True
#generate n spheres
for i in range(numSpheres):
s = sphere()
spheres.append(s)
#while not every single sphere has collided with another sphere, grow the sphere
while(allSpheresCollided() == False):
for sphere in spheres:
if sphere.canMove():
sphere.grow()
#create sphere meshes
for sphere in spheres:
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=3, radius=sphere.r, enter_editmode=False, align='WORLD', location=sphere.pos, scale=(1, 1, 1))
@Gholamrezadar
Copy link

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment