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.

Results

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 JACK_FINAL.ma which contains the RJ45 plug model and materials that the script instances.

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

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.append((random.random()-0.5)*mult)
    if(XZ):
        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)
    if(child):
        points = random.randint(4,radius)
        amp = (random.random()*2)
    else:
        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())));
        
        if(i==1):
            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)
    cmds.select(cv,r=True)
    cmds.delete()    
    
    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)
            cmds.select(rt)
            cmds.sets(rt,fe=colours[random.randint(0,5)])
    
    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):
                cmds.select(sourceObject)                
                objects[ii] = cmds.instance()[0]
                z = -radius + random.randint(round(-radius/4),round(radius/4))
            else:
                objects[ii] = cmds.spaceLocator()[0]
                if(s == 0):
                    z = -random.randint(round(-radius/4),round(radius/4))
                else:
                    z = (random.random() * radius)+1
                r = 0            
            
            o = objects[ii]
            if(ii == 0):
                global id
                cmds.select(cableObject)
                cableStub = cmds.duplicate(n="Cable_"+str(id)+"_"+str(shift))[0]; id+=1;
                objects[2] = cableStub
                if(s != 0 ):
                    cmds.scale(0.3,0.3,0.3,r=True)
                cmds.parent(cableStub,o)
                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
    generateCables(1,8,0,i);

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.