Created
September 5, 2020 06:42
-
-
Save Airyzz/4dfd3b9e70e9d873f527b89e56a10c34 to your computer and use it in GitHub Desktop.
Blender Sphere Packing Generator
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
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)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks.