Internet - Generative 3D with Maya and Python

By Stephen Holdaway

2 Oct, 2011

MDDN311 Project 2: Genesis

For this project you will create a form using generative techniques in Maya with Python scripts.


Development images

My initial idea was to have one cable coming out of a sphere of cables with jacks pointing out, evenly distributed across the surface:

At some point, I changed direction and decided to render wireless/radio waves with the network cables I was already generating:

Finally, I removed one end of the cable and used my existing code to generate smaller cables coming from the end of each main cable:

The python script

The following Python script was written for Autodesk Maya 2011 to generate scenes like the ones at the top of this page. It requires the file which contains the RJ45 plug model and materials that the script instances.

# "Internet" v5 by Stephen Holdaway
# Source models required: (RJ45 Jack w/ locator -

import maya.cmds as cmds
import math
import random

cableObject = "JACK_FINAL:cable_"
sourceObject = "JACK_FINAL:RJ45_Locator"
recursed = False
id = 0

def vAdd(l1,l2):
    o = []    
    for i in range(3):
        o.append(l1[i] + l2[i])
    return o

def vSub(l1,l2):
    o = []
    for i in range(3):
        o.append(l1[i] - l2[i])
    return o

def vDiv(l1,v = 0.0):
    o = []
    for i in range(3): 
        o.append(l1[i] / float(v))
    return o
def vMult(l1,v):
    o = []    
    for i in range(3):
        o.append(l1[i] * v)
    return o

def vGen(mult=1, XZ = False):
    o = []
    for i in range(3):
        o[1] = 0;
    return o

def drawCable(start, end, objects, radius, child):
    # Draw Cable: create a curve with noise between two points and extrude a mesh using it
    # start          -    start co-ords as [x,y,z]
    # end            -    co-ords as [x,y,z]
    # objects        -    list of object names as [start_object,end_object,cable_object]
    # radius         -    radius of area of work in
    # child          -    boolean: is this cable a child of another
    cv = cmds.curve( p=(start), d=3)
        points = random.randint(4,radius)
        amp = (random.random()*2)
        points = random.randint(4,radius*2)
        amp = (random.random()*3)+1
    vec = vDiv(vSub(start,end),points)
    prevCV = start
    for i in range(points-1):
        p = vSub(start,vMult(vec,i+1))
        p[1] += amp*math.sin(math.radians(i*(90*random.random())));
            rx = math.atan2(p[2] - start[2], p[1] - start[1]) * (180/math.pi)
            cmds.setAttr(objects[0]+".rotateX", rx);
        prevCV = p;
        cmds.curve(cv, a=True, p=(p))
    cmds.curve(cv, a=True, p=(end))
    cmds.polyExtrudeEdge(objects[2]+".e[0:11]",kft=True, d=(points*10), inc=cv, sma=180, lrz=3600, ch=False),r=True)
    global recursed
    if(recursed == False):
        recursed = True;
        colours = ["JACK_FINAL:mia_material4SG1","JACK_FINAL:mia_material3SG1","JACK_FINAL:mia_material6SG1","JACK_FINAL:mia_material3SG1","JACK_FINAL:mia_material7SG1","JACK_FINAL:mia_material3SG1"]
        for i in range(8):
            rt = generateCables(1, radius, s = end)
    return objects[2]

def generateCables(count, radius, s = 0, shift = 0):
    # Generate two points within a radius
    # count          -    number of sets (wires) to generate
    # radius         -    radius of area of work in
    # s              -    start co-ords as [x,y,z]: when provided only one point is generated (relative to the given point)
    for i in range(count):
        points = [[],[]]
        objects = ['','','']
        child = False
        for ii in range(2):
            if(ii == 0 and s == 0):
                objects[ii] = cmds.instance()[0]
                z = -radius + random.randint(round(-radius/4),round(radius/4))
                objects[ii] = cmds.spaceLocator()[0]
                if(s == 0):
                    z = -random.randint(round(-radius/4),round(radius/4))
                    z = (random.random() * radius)+1
                r = 0            
            o = objects[ii]
            if(ii == 0):
                global id
                cableStub = cmds.duplicate(n="Cable_"+str(id)+"_"+str(shift))[0]; id+=1;
                objects[2] = cableStub
                if(s != 0 ):
                r = 180
            x = shift/2.0
            y = random.randint(round(-radius/2),round(radius/2))
            if(ii==0 and s != 0):
                 x = s[0]
                 y = s[1]
                 z = s[2]
            if(ii==1 and s != 0):
                 x = s[0] + (random.random()-0.5)*2
                 z = s[2] + z
                 child = True
            points[ii] = [x,y,z]
            cmds.setAttr(o+".translateX", x)
            cmds.setAttr(o+".translateY", y)
            cmds.setAttr(o+".translateZ", z)
            cmds.setAttr(o+".rotateY", r)       
        return drawCable(points[0], points[1], objects, radius, child)

for i in range(3):
    recursed = False

This is a backdated post. The publish date reflects when the it would have been posted originally, however the actual publish date was later. This post was last modified 10 Oct, 2012.