Mar 022011
 

This is a simple script I wrote that generates meshes using DLA.

I made a little demo animation where I ran the mesh as a cloth sim.

print("-----GO-----")
import bpy
import random
from math import sin, cos, pi, sqrt
from mathutils import Vector

HardRadius = 2
RandWalkRange = .15
StickThresh = .15	   #distance threshold to accrete
MaxVerts = 100		#stop when this many verts have been added
seedLOC = Vector((0.0,0.0,0.0))

D3 = True

mname = "DLAtest"

def brownian():
	dx = random.gauss(0, RandWalkRange)
	dy = random.gauss(0, RandWalkRange)
	dz = random.gauss(0, RandWalkRange) 
	return Vector((dx, dy, dz))

####returns a new wanderer on sphere
def newWanderer():  
	randAngleA = random.uniform(0,2*pi)
	randAngleB = random.uniform(0,2*pi) 
	x = HardRadius * sin(randAngleA) * cos(randAngleB)
	y = HardRadius * sin(randAngleA) * sin(randAngleB)
	z = HardRadius * cos(randAngleA)
	return Vector((x, y, z))

def dist(A, B):
	xd = B.x-A.x
	yd = B.y-A.y
	zd = B.z-A.z
	return sqrt(xd*xd + yd*yd + zd*zd)

def wanderLoop(ob):
	wand = newWanderer()
	mmesh = ob.data
	while len(mmesh.vertices) < MaxVerts:
		brown = brownian()
		wand.x += brown.x
		wand.y += brown.y
		if D3: wand.z += brown.z
		else: wand.z = 0
		if  abs(wand.x) > HardRadius or 
			abs(wand.y) > HardRadius or 
			abs(wand.z) > HardRadius:
				wand = newWanderer()
				
		for vert in range(len(mmesh.vertices)):
			dpt = dist(wand, mmesh.vertices[vert].co)
			dZ = dist(wand, seedLOC)			
			if dpt < StickThresh:
				st = str(len(mmesh.vertices)+1) + " of " + str(MaxVerts) + " has been assimilated"
				print(st, dpt)
				addPoint(ob, wand, vert)
				wand = newWanderer()
				pass

####Object, point to add, index of vert to connect to (None is -1)
def addPoint(ob, pt, conni):
	mmesh = ob.data
	mmesh.vertices.add(1)
	vcounti = len(mmesh.vertices)-1
	mmesh.vertices[vcounti].co = [pt.x, pt.y, pt.z]
	if conni > -1:
		mmesh.edges.add(1)
		ecounti = len(mmesh.edges)-1
		mmesh.edges[ecounti].vertices = [conni, vcounti]


def newDLAMesh(mname):
	mmesh = bpy.data.meshes.new(mname)
	omesh = bpy.data.objects.new(mname, mmesh)
	bpy.context.scene.objects.link(omesh)
	addPoint(omesh, seedLOC, -1)	
	return omesh

ob = newDLAMesh("testDLA")
wanderLoop(ob)



  3 Responses to “Diffusion-Limited Aggregation Mesh Generator”

  1. Man this site is great, thanks for sharing all this material! I hope you donĀ“t mind, but I’ll be doing a post on my blog about your site.. Congrats and thanks again for sharing.

    • Very cool, Thanks!

    • I figured it out. While piknog around for an update function I found out how to set a key for the energy button. To set a key for the lamps energy you do the following: bpy.data.lamps[‘Lamp’].keyframe_insert(data_path = energy )I figured out the data path by right clicking on the energy button and clicking Copy Data Path So I loop through the frames setting a key on each frame then it was just a matter of playing the animation. Hovering over the play button showed that was as simple as doing this:bpy.ops.screen.animation_play()Here is my final code. (It’s probably going to mess up the identation)import bpyimport randomframe = 0endframe = 30bpy.ops.anim.change_frame(frame = frame) # make sure we are at frame zerofor i in range(frame,endframe+1): # add one because range doesn’t include last number # For loop sets random energy keyframes for Lamp’ bpy.data.lamps[‘Lamp’].energy = random.random() bpy.data.lamps[‘Lamp’].keyframe_insert(data_path = energy ) bpy.ops.anim.change_frame(frame = frame) frame = frame + 1bpy.ops.anim.change_frame(frame = 0) # make sure we are at frame zerobpy.ops.screen.animation_play()I ended up not needing the time module after all. I learned a lot from doing this!

Leave a Reply