Sunday, July 12, 2009

Chinese whispers

Chinese whispers

::: SYNOPSIS :::
My idea is to have 1EMITER, 1RECEPTOR, and n number of TRANSMITOR!
The aim of this script is to bring the information from the
EMITER, to the RECEPTOR by the TRANSMITOR!
The information is symbolized by the red color, the white color symbolized the un-information ...
The
EMITER and the RECEPTOR doesn't move, only theTRANSMITOR can move!...

When a
TRANSMITOR hit the EMITER, the TRANSMITOR become red, the EMITER become white!
Then when this red-TRANSMITOR hit another black-TRANSMITOR, the red become black again, and the black become red!
The Information is transmitted! ... When finally the
RECEPTOR is hitting by a red TRANSMITOR, the script stop! ...

::: AUTO-COMMENTS :::
- Does this script too simple?
- I will try to clean a little bit the hit part! It's a little bit messy, and I found a new way to do it!

- I also want to script another scenerio based on the same principe

####################################
## INFORMATIONS DIFFUSION
## Chinese whispers
####################################

import maya.cmds as cmds
import maya.mel as mel
import random
import math


# Function to create shader
def createShader(color, transparency=0, type="lambert", name="shader"):
#steps to create a new material
shadingNode1 = cmds.shadingNode(type, asShader=1, name=name)
shadingNode2 = cmds.sets(renderable=1, noSurfaceShader = 1, empty=1, name=name)
cmds.connectAttr(shadingNode1+".outColor", shadingNode2 + ".surfaceShader", force=1)
#steps to modify material attributes
cmds.setAttr(shadingNode1 + ".color", color[0],color[1], color[2]) #color in r g b values
cmds.setAttr(shadingNode1 + ".transparency", transparency, transparency, transparency)

return shadingNode2


# Function to create shader I need
def myshaders():
# Create the transmitter shader => no information
if cmds.objExists('noir'):
# stupid line just to say to python to do nothing!
nothing = 0
else:
noir = createShader((0,0,0), transparency=0, type="lambert", name="noir")

# Create the Receptor shader => awaiting the information
if cmds.objExists('blanc'):
# stupid line just to say to python to do nothing!
nothing = 0
else:
blanc = createShader((255,255,255), transparency=0, type="lambert", name="blanc")

# Create the transmitter shader => information
if cmds.objExists('rouge'):
# stupid line just to say to python to do nothing!
nothing = 0
else:
rouge = createShader((255,0,0), transparency=0, type="lambert", name="rouge")

# Create the box shader, transparent to see what's happen inside! =)
if cmds.objExists('transparent'):
# stupid line just to say to python to do nothing!
nothing = 0
else:
transparent = createShader((0,0,0), transparency=.9, type="lambert", name="transparent")

# Function to apply the shader
def applyShaderOnObject(obj, shader):
cmds.sets(obj, e=1, forceElement=shader)

# SYNOPSIS :::
# My idea is to have 1EMITER, 1RECEPTOR, and n number of TRANSMITOR!
# The aim of this script is to bring the information from the EMITER, to the RECEPTOR by the TRANSMITOR!
# The information is symbolized by the red color, the white color symbolized the un-information ...
# The EMITER and the RECEPTOR doesn't move, only the TRANSMITOR can move!...

# When a TRANSMITOR hit the EMITER, the TRANSMITOR become red, the EMITER become white!
# Then when this red-TRANSMITOR hit another black-TRANSMITOR, the red become black again, and the black become red!
# The Information is transmitted! ... When finally the RECEPTOR is hitting by a red TRANSMITOR, the script stop! ...

def hit(hit, agent):
### define what to do when it some collision is detected
if hit == "wall_rigid":
return

agentRole = cmds.getAttr(agent + ".role")
hitRole = cmds.getAttr(hit + ".role")
agentShader = cmds.getAttr(agent + ".shader")
hitShader = cmds.getAttr(hit + ".shader")

# If the emitter hit a transmitter
if agentRole == "emitter":
if hitRole == "transmitters":
#print agentRole # = emitter
#print hitRole # = transmitter

if agentShader == 'rouge1':
# change the color of the transmitter from black to red
obj = cmds.getAttr(hit+".obj")
applyShaderOnObject(obj, 'rouge1')
cmds.setAttr(hit+".shader", 'rouge1', type="string")

# change the color of the emitter from red to black
obj = cmds.getAttr(agent+".obj")
applyShaderOnObject(obj, 'noir1')
cmds.setAttr(agent+".shader", 'noir1', type="string")


# If a transmiter hit a emitter
if agentRole == "transmitters":
if hitRole == "emitter":
#print agentRole # = trans
#print hitRole # = emit

if hitShader == 'rouge1':
# change the color of the emitter from red to black
obj = cmds.getAttr(hit+".obj")
applyShaderOnObject(obj, 'noir1')
cmds.setAttr(hit+".shader", 'noir1', type="string")

# change the color of the transmitter from black to red
obj = cmds.getAttr(agent+".obj")
applyShaderOnObject(obj, 'rouge1')
cmds.setAttr(agent+".shader", 'rouge1', type="string")


# If a transmitter hit another transmitter
if agentRole == "transmitters":
if hitRole == "transmitters":

if agentShader == 'rouge1':
# change the color of the frist transmitter from black to red
obj = cmds.getAttr(hit+".obj")
applyShaderOnObject(obj, 'rouge1')
cmds.setAttr(hit+".shader", 'rouge1', type="string")

# change the color of the second transmitter from red to black
obj = cmds.getAttr(agent+".obj")
applyShaderOnObject(obj, 'noir1')
cmds.setAttr(agent+".shader", 'noir1', type="string")


if hitShader == 'rouge1':
# change the color of the frist transmitter from red to black
obj = cmds.getAttr(hit+".obj")
applyShaderOnObject(obj, 'noir1')
cmds.setAttr(hit+".shader", 'noir1', type="string")

# change the color of the second transmitter from black to red
obj = cmds.getAttr(agent+".obj")
applyShaderOnObject(obj, 'rouge1')
cmds.setAttr(agent+".shader", 'rouge1', type="string")


# And Finally, if an emitter hit the receptor!
if agentRole == "receptor":
if hitRole == "transmitters":
#print agentRole # = receptor
#print hitRole # = emitter

if hitShader == 'rouge1':
# change the color of the transmitter from red to black
obj = cmds.getAttr(hit+".obj")
applyShaderOnObject(obj, 'noir1')
cmds.setAttr(hit+".shader", 'noir1', type="string")

# change the color of the receptor form white to red
obj = cmds.getAttr(agent+".obj")
applyShaderOnObject(obj, 'rouge1')
cmds.setAttr(agent+".shader", 'rouge1', type="string")

# means that the information is propely transmitted
# so, stop the animation, and print a feedback
cmds.play( state=False )
frame = cmds.currentTime( query=True )
print "INFORMATION TRANSMITED IN", frame, "FRAMES"


# if an emitter hit the receptor!
if agentRole == "transmitters":
if hitRole == "receptor":
#print agentRole # = emit
#print hitRole # = trans

if agentShader == 'rouge1':
# change the color of the receptor form white to red
obj = cmds.getAttr(hit+".obj")
applyShaderOnObject(obj, 'rouge1')
cmds.setAttr(hit+".shader", 'rouge1', type="string")

# change the color of the transmitter from red to black
obj = cmds.getAttr(agent+".obj")
applyShaderOnObject(obj, 'noir1')
cmds.setAttr(agent+".shader", 'noir1', type="string")

# means that the information is propely transmitted
# so, stop the animation, and print a feedback
cmds.play( state=False )
frame = cmds.currentTime( query=True )
print "INFORMATION TRANSMITED IN", frame, "FRAMES"



class Agent:
def __init__(self, solver, role, position=(0,0,0), size=(3,3,3), color=(0,0,0), objType="sphere", rigidType="active", bounciness=.6, collide=1, mass=1, speed=5):
#set agent atributes
self.bounciness = bounciness
self.collide = collide
self.rigidType = rigidType
self.solver=solver
self.role = role
self.initialScale = size
self.mass=mass
self.speed = speed

#create the agent and scale it
self.object = cmds.polySphere(ax=(0,0,1))
cmds.scale(size[0], size[1], size[2])
#apply a color to the agent
#set the object color

applyShaderOnObject(self.object[0], color)

#create the rigid body
self.rigid = cmds.rigidBody(self.object,
name=self.object[0] + "_rigid",
p=position,
b=self.bounciness,
impulse=(0,0,0),
sio=objType, #stand in object
cc = 1, #contact count
cp = 1, #contact position
cn = 1, #contact name
si = (190,190,190),
m=mass,
solver=self.solver)

#add attribute to the rigid body to store the type of agent
cmds.select(self.rigid, r=1)
cmds.addAttr(ln="role", dt="string", keyable=1, w=1)
cmds.setAttr(self.rigid + ".role", self.role, type="string")

cmds.addAttr(ln="obj", dt="string", keyable=1, w=1)
cmds.setAttr(self.rigid + ".obj", self.object[0] , type="string")

cmds.addAttr(ln="shader", dt="string", keyable=1, w=1)
cmds.setAttr(self.rigid + ".shader", color , type="string")

self.applyExpression(speed)

def applyExpression(self, speed):
"Function to apply the expression to the agent"
#first disconnect the rotation attributes because we want to controll it via expressions
cmds.disconnectAttr (self.rigid + "ry.output", self.object[0] + ".rotateY")
cmds.disconnectAttr (self.rigid + "rx.output", self.object[0] + ".rotateX")
cmds.disconnectAttr (self.rigid + "rz.output", self.object[0] + ".rotateZ")

# Create expression for VehicleF with a random multiplier added to the expression.
randX = random.uniform(-speed,speed)
randY = random.uniform(speed,-speed)

expString = "// Set wander motion of vehicle and add random multipliers.\n"

if self.role == "transmitters":
####COMPOSE THE EXPRESSION STRING
#now put the text above in a python string
#the first lines define how the agent will wander

expString += "%s.impulseX" % self.rigid
expString += " = (cos(time*%f));\n" % randX
expString += "%s.impulseY" % self.rigid
expString += " = ((noise(time) * %f));\n\n" % randY


#the second part, how it rotates according to the direction it is going (velocity vector)
expString += "// Set orientation of Vehicle according to the velocity direction.\n"
expString += "float $fVel[];\n"
expString += "$fVel = `getAttr %s.velocity`;\n\n" % (self.rigid)
expString += "%s.rotateX = 0;\n" % self.object[0]
expString += "%s.rotateZ = atan2d( $fVel[0], $fVel[1] );\n" % (self.object[0])
expString += "%s.rotateY = 0;\n\n" % self.object[0]


#the third part, checking bumps on other agents
expString += "//checking bumps on other agents\n"
expString += "string $lastHit;\n"
expString += "if (%s.contactCount > 0){\n" % self.rigid
expString += " int $contactCount = `getAttr %s.contactCount`;\n" % self.rigid
expString += " $lastHit = `getAttr %s.contactName[0]`;\n" %self.rigid
expString += ' string $rigid = "%s";\n' % self.rigid
expString += ' python("hit(\'"+$lastHit+"\', \'"+ $rigid +"\')");\n'
expString += "};//endif\n"

self.expString = expString
cmds.expression(s=expString)







##############################################
class Crowd:
def __init__(self, numAgents=20, scaleRecept=2.5, scaleTrans=2, minPosition=-70, maxPosition=70, walls=1, speed=5):
#set the playback options to increase the time range
cmds.playbackOptions(min= 1, max=5000)
self.numAgents = numAgents
self.minPosition = minPosition
self.maxPosition = maxPosition
self.scaleRecept = scaleRecept
self.scaleTrans = scaleTrans
self.speed = speed

#get any selected objects
self.createBorders(scaleRecept,maxPosition)
self.wallObjs = cmds.ls(sl=1)

#create the rigid solver
self.solver = self.createSolver()
#create the agents
self.createAgents(scaleRecept, scaleTrans, speed)
#create the walls
if walls: self.makeWalls()


# Create a box to contain the balls
def createBorders(self, scaleRecept,maxPosition):
cmds.polyCube(n="border", ax=(0,0,0), w=((maxPosition*2)+(scaleRecept*2)), h=((maxPosition*2)+(scaleRecept*2)), d=(scaleRecept*2))
cmds.polyNormal( nm=0 )
myshaders()
applyShaderOnObject("border", 'transparent1')

cmds.select("border")


# Create Solver
def createSolver(self):
solver = cmds.rigidSolver(create=1, current=1, name="crowdSolver", velocityVectorScale=0.1, displayVelocity=1, sc=1, ctd=1)
cmds.setAttr(solver + ".allowDisconnection", 1)
return solver

# Create x numbers of transmittors
def createAgents(self, scaleRecept, scaleTrans, speed):
myshaders()
self.speed = speed
transmitters = ['transmitters', (scaleTrans,scaleTrans,scaleTrans), 1, 'noir1'] #name, scale, mass, color
emitter = ['emitter', (scaleRecept,scaleRecept,scaleRecept), 1000, 'rouge1'] #name, scale, mass, color
receptor = ['receptor', (scaleRecept,scaleRecept,scaleRecept), 1000, 'blanc1'] #name, scale, mass, color

self.transmitlist = []
self.emitlist = []
self.receptlist = []


# Create the emeter
x = float(random.uniform(self.minPosition,self.maxPosition))
y = float(random.uniform(self.minPosition,self.maxPosition))
z = 0

emitagent = Agent(self.solver, emitter[0], size=emitter[1], color=emitter[3], position=(x,y,z), bounciness=0, mass=emitter[2], speed=speed)
liste = (self.solver, emitagent)
self.emitlist.append(liste)

# Create the receptor
x = float(random.uniform(self.minPosition,self.maxPosition))
y = float(random.uniform(self.minPosition,self.maxPosition))
z = 0

receptagent = Agent(self.solver, receptor[0], size=receptor[1], color=receptor[3], position=(x,y,z), bounciness=0, mass=receptor[2], speed=speed)
liste = (self.solver, receptagent)
self.receptlist.append(liste)


# Create n transmiters
for i in range(self.numAgents):
#get random x and y
x = random.uniform(self.minPosition,self.maxPosition)
y = random.uniform(self.minPosition,self.maxPosition)
z = 0

#create the agents
transagent = Agent(self.solver, transmitters[0], position=(x,y,z), size=transmitters[1], color=transmitters[3], mass=transmitters[2], speed=speed)
liste = (self.solver, transagent)
self.transmitlist.append(liste)


def makeWalls(self):
#get selected object,
#which should be already with its normals facing to the right directions,
#and convert it to passive rigid bodies
if len(self.wallObjs) == 0:
return "No wall objects were selected."
else:
for w in self.wallObjs:
self.wallRigid = cmds.rigidBody(w, passive=1, name= "wall_rigid", bounciness=.8)

########################################


c=Crowd(numAgents=50, walls=1, speed=5)

Friday, July 10, 2009

Predator-Prey crowd system


The goal of the script was to create a primary state of equality and to add some fields which would tarnsform(change) the boids behaviour. Therefore from simple wanderers (with no leaders) some boids would become either preys or predators.

If a predator would hit a wanderer, the number of predators would increase by one. If the predator would hit a prey, the number of preys would decrease by one and the number of predators would be the same. If a predator would enter the "force" field which changes the boids behaviour to preys, it would become a prey. If a prey would enter the "force" field which changes the boids behaviour to predators, it would become a predator.




import maya.cmds as cmds
import random


# Main
# ____
class Crowd:
def __init__(self):
#def crowdMain():
self.vNumber = 10
self.obst = 0
self.gforces = 0
self.UIelements = {}
cmds.playbackOptions(min= 1, max=500)
self.crowdSystemUI()
#end if
#end def __init__


def crowdSystemUI(self):
self.UIelements["window"] = cmds.window(title="Crowd System",
widthHeight=(300, 200)
)

self.UIelements["form"] = cmds.formLayout()
txt = cmds.text(label="Number of Vehicles")
collection = cmds.radioCollection()
radiob1 = cmds.radioButton(label="10", data=1, changeCommand=self.changeVnumber)
radiob2 = cmds.radioButton(label="20", onCommand="vNumber = 20")
cmds.setParent(upLevel=1)
cmds.setParent(upLevel=1)

txtOB = cmds.text(label="Obstacles")
collection2 = cmds.radioCollection()
radiob3 = cmds.radioButton(label="On", changeCommand=self.changeObst)
radiob4 = cmds.radioButton(label="Off")
cmds.setParent(upLevel=1)
cmds.setParent(upLevel=1)

txtGF = cmds.text( label = "Global Forces")
collection3 = cmds.radioCollection()
radiob5 = cmds.radioButton(label= "On" ,changeCommand =self.changeGforces)
radiob6 = cmds.radioButton(label="Off")
cmds.setParent(upLevel=1)
cmds.setParent(upLevel=1)

cmds.radioCollection(collection, edit=1, select=radiob1)
cmds.radioCollection(collection2, edit=1, select=radiob4)
cmds.radioCollection(collection3, edit=1, select=radiob6)

# Place Vehicle options
form = self.UIelements["form"]
cmds.formLayout(form,
edit=1,
attachForm= [
( txt, "top", 20),
(txt ,"left", 70),
(radiob1,"top", 10),
(radiob1,"left", 20),
(radiob2,"top", 30),
(radiob2,"left", 20)
]
)

# Place environment options
cmds.formLayout(form,
edit=1,
attachForm= [
(txtOB, "top", 80),
(txtOB, "left", 80),
(radiob3, "top", 80),
(radiob3, "left", 150),
(radiob4 ,"top", 80),
(radiob4, "left", 190),
(txtGF, "top", 110),
(txtGF, "left", 63),
(radiob5, "top", 110),
(radiob5, "left", 150),
(radiob6, "top", 110),
(radiob6, "left", 190)
]
)

# Create buttons
button1 = cmds.button(label = "Create")
button2 = cmds.button(label = "Cancel")

# Place buttons in the window
cmds.formLayout(form,
edit=1,
attachForm =[
(button1, "bottom", 10),
(button1, "left", 185),
(button2, "bottom", 10),
(button2, "right", 10)
]
)

# Add the commands to the buttons.

cmds.button(button1, edit=1, command=self.createCrowd )
cmds.button(button2, edit=1, command=self.deleteUI )

cmds.showWindow(self.UIelements["window"])

##############################################################
def createCrowdSolver(self):
self.crowdSolver = cmds.rigidSolver( create=1,
current=1,
name="crowdSolver",
velocityVectorScale=0.5,
displayVelocity=1,
sc=1
)
cmds.setAttr(self.crowdSolver + ".allowDisconnection", 1)

def createVehicle(self, i, vType):
"Creates a Vehicle"
if vType == "F":
w = 2
h = 2.5
d = 2
else:
w=5
h=3.5
d=5
v = cmds.polyCube(name="vehicle%s_%d" % (vType, i), width = w, height = h, depth = d)
#Add a Vehicle force field for follower.
field = cmds.radial( position=(0, 0, 0),
name = "vehicle%sForce_%d" % (vType, i),
magnitude=50,
attenuation=0.3,
maxDistance = 8.0
)
cmds.parent(field[0], v[0])
cmds.hide (field)
'''
if vType == "L":
# Add leader field
lRadial = cmds.radial( position = (0, 0, 0),
name = "vehicleGlobalLeadForce_%d" % i,
magnitude = -1,
attenuation = 0.2,
maxDistance = 50
)
cmds.parent (lRadial[0], v[0])
cmds.hide (lRadial)
'''
# Make the Vehicle a Rigid Body with random placement.
rigid = cmds.rigidBody(v[0],
name="rigidVehicle%s_%d" % (vType, i),
active=1,
mass=1,
bounciness=0,
damping= 1.5 ,
position = (random.uniform(-70,70), random.uniform(-70,70), 0),
impulse =( 0, 0, 0),
standInObject="cube",
solver= self.crowdSolver
)

cmds.disconnectAttr (rigid + "ry.output", v[0] + ".rotateY")
cmds.disconnectAttr (rigid + "rx.output", v[0] + ".rotateX")
cmds.disconnectAttr (rigid + "rz.output", v[0] + ".rotateZ")

# Create expression for VehicleF with a random multiplier added to the expression.
randX = random.uniform(-3,3)
randY = random.uniform(3,-3)
expString = "// Set wander motion of vehicle and add random multipliers.\n"
expString += "%s.impulseX" % rigid
expString += " = sin(time * %f);\n" % randX
expString += "%s.impulseY" % rigid
expString += " = (noise(time) * %f);\n\n" % randY
expString += "// Set orientation of Vehicle according to the velocity direction.\n"
expString += "float $fVel%d[];\n" % i
expString += "$fVel%d = `getAttr %s.velocity`;\n\n" % (i,rigid)
expString += "%s.rotateX = 0;\n" % v[0]
expString += "%s.rotateY = atan2d( $fVel%d[0], $fVel%d[2] );\n" % (v[0],i,i)
expString += "%s.rotateZ = 0;\n" % v[0]
expString += "string $ContactNames = `getAttr %s.cnn`;\n" % rigid
expString += "print($ContactNames);\n"

#print expString
exp = cmds.expression(s=expString )
######################################################################### start w08
if vType == "F":
return [rigid, field]
else:
return [rigid, field, lRadial]

def createCrowd(self, *args) :

self.collectObjects = cmds.ls(sl=1) ###################################### get selected objects

# Bring in ints and string from interface.
# Vehicle creation for crowd system.
# Create a master crowdSolver for all Vehicles.
self.createCrowdSolver()

# Get total number of Vehicles from interface options.
if self.vNumber == 10:
FvNumber = 10 # Followers
#LvNumber = 2 # Leaders
elif self.vNumber == 20:
FvNumber = 20 # Followers
#LvNumber = 2 # Leaders

#if (self.gforces == 1): self.makeGforces() # Check Global Forces option.


# Basic Vehicle model type: follower
#____________________________
followers = []
for i in range(FvNumber):
v = self.createVehicle(i, "F")
followers.append(v)

# Basic Vehicle model type: Leader
#_________________________________
#leaders = []
#for i in range(LvNumber):
# v = self.createVehicle(i, "L")
# leaders.append(v)
##########################
# Connect the fields nested loops.
# ________________________________
'''
for i in range(LvNumber): # Connect Leaders to Followers both fields.
fieldL = leaders[i][1]
fieldLG = leaders[i][2]
for j in range(FvNumber):
rigidF = followers[j][0]
cmds.connectDynamic(rigidF, fields=fieldL)
cmds.connectDynamic(rigidF, fields=fieldLG)





for i in range(FvNumber): # Connect Followers to Leaders
fieldF = followers[i][1]
for j in range(LvNumber):
rigidL = leaders[j][0]
cmds.connectDynamic(rigidL, fields=fieldF)


# Connect same type Vehicles to each other. Disconnect Vehicle from itself.

for i in range(LvNumber): # Connect Leaders to Leaders
rigidL1 = leaders[i][0]
fieldL1 = leaders[i][1]
for j in range(LvNumber):
rigidL2 = leaders[j][0]
fieldL2 = leaders[j][1]
cmds.connectDynamic(rigidL2, fields=fieldL1)

cmds.connectDynamic(rigidL1, delete=1, fields=fieldL1)
'''
for i in range(FvNumber): # Connect Follower to Followers
rigidF1 = followers[i][0]
fieldF1 = followers[i][1]
for j in range(FvNumber):
rigidF2 = followers[j][0]
fieldF2 = followers[j][1]
cmds.connectDynamic(rigidF2, fields=fieldF1)

cmds.connectDynamic(rigidF1, delete=1, fields=fieldF1)

######################################################################################## skip this global forces thing
# Connect the Global Forces to both types of Vehicles if option is on.

if self.gforces:
self.makeGforces()

compass = [ "N", "S", "E", "W" ]
for i in range(LvNumber):
for c in range(len(compass)):
cmds.connectDynamic(leaders[i][0], fields = "Gforce" + compass[c])

for i in range(FvNumber):
for c in range(len(compass)):
cmds.connectDynamic(followers[i][0], fields = "Gforce" + compass[c])


# Build Obstacles if option is selected.
if self.obst: self.collectObstacles()

# Disable warning.

cmds.cycleCheck(e=0)

# End of createCrowd def

def collectObstacles(self):
print "collecting obstacles!!"
if len(self.collectObjects) == 0: ### show on __init__ def
return "No obstacle objects were selected."
else:
print "elseeeee"
for ob in self.collectObjects:
print ob
cmds.rigidBody(ob, passive=1, name= ob + "_RigidB", bounciness=2.0)

#end def collectObstacles


# Make Global Forces with an interface.
#______________________________________


########################################### UI functions (for radio buttons)
def changeVnumber(self, *args):
if args[0] == "true":
self.vNumber = 10
else:
self.vNumber = 20
print "vNumber:",self.vNumber
def changeObst(self, *args):
if args[0] == "true":
self.obst = 1
else:
self.obst = 0
print "Obst:", self.obst
def changeGforces(self, *args):
if args[0] == "true":
self.gforces = 1
else:
self.gforces = 0
print "gforces:", self.gforces
def deleteUI(self, *args):
cmds.deleteUI(self.UIelements["window"])
self.UIelements = {}

############### call the class
c = Crowd()

And part of the second attempt:

import maya.cmds as cmds
import maya.mel as mel
import random
import math

def hit(hit, agent):
### define what to do when it some collision is detected
#all transformations are made only on the agent, as the hit object will perform the same queries on this agent
#if it hit the cube, ignore
if hit == "wall_rigid":
return
agentRole = cmds.getAttr(agent + ".role")
hitRole = cmds.getAttr(hit + ".role")
if hitRole == agentRole:
#check if both are bad
if hitRole == "bad":
#then shrink
cmds.scale(.9,.9,.9, agent, r=1)
else:
#if good, increase size
cmds.scale(1.1,1.1,1.1, agent, r=1)
elif hitRole != agentRole:
if hitRole == "bad":
#means agent role is good
cmds.scale(.90,.90,.90, agent, r=1)
elif hitRole == "good":
#means agent was bad
cmds.scale(1.1,1.1,1.1, agent, r=1)


#function to create shader
def createShader(color, transparency=0, type="lambert"):
#steps to create a new material
shadingNode1 = cmds.shadingNode(type, asShader=1)
shadingNode2 = cmds.sets(renderable=1, noSurfaceShader = 1, empty=1, name=shadingNode1+"SG")
cmds.connectAttr(shadingNode1+".outColor", shadingNode2 + ".surfaceShader", force=1)
#steps to modify material attributes
cmds.setAttr(shadingNode1 + ".color", color[0],color[1], color[2]) #color in r g b values
cmds.setAttr(shadingNode1 + ".transparency", transparency, transparency, transparency)

return shadingNode2

def applyShaderOnObject(obj, shader):
cmds.sets(obj, e=1, forceElement=shader)




class Agent:
def __init__(self, solver, role, position=(0,0,0), size=(3,3,3), color=(0,0,0), objType="cube", rigidType="active", bounciness=.6, collide=1):
#set agent atributes
self.bounciness = bounciness
self.collide = collide
self.rigidType = rigidType
self.solver=solver
self.role = role
self.initialScale = size
#create the agent and scale it
self.object = cmds.polySphere(ax=(0,0,1))
cmds.scale(size[0], size[1], size[2])
#apply a color to the agent
#set the object color
sh = createShader(color, transparency=0, type="lambert")
applyShaderOnObject(self.object[0], sh)

#create the rigid body
self.rigid = cmds.rigidBody(self.object,
name=self.object[0] + "_rigid",
p=position,
b=self.bounciness,
impulse=(0,0,0),
sio=objType, #stand in object
cc = 1, #contact count
cp = 1, #contact position
cn = 1, #contact name
solver=self.solver)

#add attribute to the rigid body to store the type of agent
cmds.select(self.rigid, r=1)
cmds.addAttr(ln="role", dt="string", keyable=1)
cmds.setAttr(self.rigid + ".role", "good", type="string")

if self.rigidType == "active":
cmds.setAttr(self.rigid + ".active", 1)
else:
cmds.setAttr(self.rigid + ".active", 0)

#apply the expression
self.applyExpression()

def applyExpression(self):
"Function to apply the expression to the agent"
#first disconnect the rotation attributes because we want to controll it via expressions
cmds.disconnectAttr (self.rigid + "ry.output", self.object[0] + ".rotateY")
cmds.disconnectAttr (self.rigid + "rx.output", self.object[0] + ".rotateX")
cmds.disconnectAttr (self.rigid + "rz.output", self.object[0] + ".rotateZ")
# Create expression for VehicleF with a random multiplier added to the expression.
randX = random.uniform(-3,3)
randY = random.uniform(3,-3)
####COMPOSE THE EXPRESSION STRING
#this is how it should look like (in MEL)
'''
// Set wander motion of vehicle and add random multipliers.
pCube1_rigid_0.impulseX = sin(time * -2.808801);
pCube1_rigid_0.impulseY = (noise(time) * -1.041035);

// Set orientation of Vehicle according to the velocity direction.
float $fVel[];
$fVel = `getAttr pCube1_rigid_0.velocity`;

pCube1.rotateX = 0;
pCube1.rotateZ = atan2d( $fVel[0], $fVel[1] );
pCube1.rotateY = 0;

//checking bumps on other agents
string $lastHit;
if (pCube1_rigid_0.contactCount > 0){
int $contactCount = `getAttr pCube1_rigid_0.contactCount`;
$lastHit = `getAttr pCube1_rigid_0.contactName[0]`;
string $rigid = "pCube1_rigid_0";
python("hit('"+$lastHit+"', '"+ $rigid +"')");
};//endif
'''
#now put the text above in a python string
#the first lines define how the agent will wander
expString = "// Set wander motion of vehicle and add random multipliers.\n"
expString += "%s.impulseX" % self.rigid
expString += " = sin(time * %f);\n" % randX
expString += "%s.impulseY" % self.rigid
expString += " = (noise(time) * %f);\n\n" % randY
#the second part, how it rotates according to the direction it is going (velocity vector)
expString += "// Set orientation of Vehicle according to the velocity direction.\n"
expString += "float $fVel[];\n"
expString += "$fVel = `getAttr %s.velocity`;\n\n" % (self.rigid)
expString += "%s.rotateX = 0;\n" % self.object[0]
expString += "%s.rotateZ = atan2d( $fVel[0], $fVel[1] );\n" % (self.object[0])
expString += "%s.rotateY = 0;\n\n" % self.object[0]
#the third part, checking bumps on other agents
expString += "//checking bumps on other agents\n"
expString += "string $lastHit;\n"
expString += "if (%s.contactCount > 0){\n" % self.rigid
expString += " int $contactCount = `getAttr %s.contactCount`;\n" % self.rigid
expString += " $lastHit = `getAttr %s.contactName[0]`;\n" %self.rigid
expString += ' string $rigid = "%s";\n' % self.rigid
expString += ' python("hit(\'"+$lastHit+"\', \'"+ $rigid +"\')");\n'
expString += "};//endif\n"

self.expString = expString
cmds.expression(s=expString)


##############################################
class Crowd:
def __init__(self, numAgents=20, minPosition=-70, maxPosition=70, walls=0):
#set the playback options to increase the time range
cmds.playbackOptions(min= 1, max=5000)
self.numAgents = numAgents
self.minPosition = minPosition
self.maxPosition = maxPosition
#get any selected objects
self.wallObjs = cmds.ls(sl=1)
#create the rigid solver
self.solver = self.createSolver()
#create the agents
self.createAgents()
#create the walls
if walls: self.makeWalls()

def createSolver(self):
solver = cmds.rigidSolver( create=1,
current=1,
name="crowdSolver",
velocityVectorScale=0.5,
displayVelocity=1,
sc=1, #showcollision
ctd=1 #contact data
)
cmds.setAttr(solver + ".allowDisconnection", 1)
return solver

def createAgents(self):
type1 = ["good", (3,3,3), (250,100,0)] #name, scale, color
type2 = ["bad", (5,5,5), (100,100,100)]
types = [type1, type2]
self.badAgents = []
self.goodAgents = []
for i in range(self.numAgents):
#get the agent type randomly
at = random.choice(types)
#get random x and y
x = random.uniform(self.minPosition,self.maxPosition)
y = random.uniform(self.minPosition,self.maxPosition)
#create the agents
a = Agent(self.solver, at[0], color=at[2], size=at[1], position=(x,y,0))
if at[0] == "good":
self.goodAgents.append(a)
else:
self.badAgents.append(a)

def makeWalls(self):
#get selected object,
#which should be already with its normals facing to the right directions,
#and convert it to passive rigid bodies
if len(self.wallObjs) == 0:
return "No wall objects were selected."
else:
for w in self.wallObjs:
self.wallRigid = cmds.rigidBody(w, passive=1, name= "wall_rigid", bounciness=.8)

########################################
c=Crowd(numAgents=30, walls=1)

Thursday, July 9, 2009

##### Bacteria War _ crowd systems
#### started 20:21 08.07.09


### import all possibly needed


### Super Plan
###Passive agents:
## BODY (obstacles__rigid body)
## BRAIN (finish area__rigid body)
##Active agents:
## BACTERIUM (agent type1)
## DRUG (agent type2)


#####################################TRANSLATING into script
####create "BODY" and Agent 3d(small - Bacterium, big - Drug)
#### have them on stage
### rename 3d objects
### run script

import maya.cmds as cmds
import maya.mel as mel
import random
import math

def hit(hit, agent):
### define what to do when it some collision is detected
#if it hit the body, ignore
if hit == "wall_rigid":
return
agentRole = cmds.getAttr(agent + ".role")
hitRole = cmds.getAttr(hit + ".role")
if hitRole == agentRole:
#check if both are Drugs
if hitRole == "Drug":
#then rotate
cmds.rotate(90,90,0)
else:
#if Bacteria, delete Bacteria
cmds.delete('agent')
elif hitRole != agentRole:
if hitRole == "Drug":
#means agent role is Bacteria
cmds.duplicate('agent')
cmds.move(0,0,0)
elif hitRole == "Bacteria":
#means agent was Drug
cmds.delete('agent')




class Agent:
def __init__(self, solver, role, position=(0,0,0), size=(3,3,3), color=(0,0,0), objType="agent", rigidType="active", bounciness=.6, collide=1):
#set agent atributes
self.bounciness = bounciness
self.collide = collide
self.rigidType = rigidType
self.solver=solver
self.role = role
self.initialScale = size
#create the agent and scale it
NameDubObj1 = []
myDubObj1 = cmds.duplicate( 'agent' )# creation ( dublication) of the elements (bacteria/drug)
self.object = myDubObj1
cmds.scale(size[0], size[1], size[2])

#create the rigid body
self.rigid = cmds.rigidBody(self.object,
name=self.object[0] + "_rigid",
p=position,
b=self.bounciness,
impulse=(0,0,0),
sio=objType, #stand in object
cc = 1, #contact count
cp = 1, #contact position
cn = 1, #contact name
solver=self.solver)

#add attribute to the rigid body to store the type of agent
cmds.select(self.rigid, r=1)
cmds.addAttr(ln="role", dt="string", keyable=1)
cmds.setAttr(self.rigid + ".role", "Bacteria", type="string")

if self.rigidType == "active":
cmds.setAttr(self.rigid + ".active", 1)
else:
cmds.setAttr(self.rigid + ".active", 0)

#apply the expression
self.applyExpression()

def applyExpression(self):
"Function to apply the expression to the agent"
#first disconnect the rotation attributes because we want to controll it via expressions
cmds.disconnectAttr (self.rigid + "ry.output", self.object[0] + ".rotateY")
cmds.disconnectAttr (self.rigid + "rx.output", self.object[0] + ".rotateX")
cmds.disconnectAttr (self.rigid + "rz.output", self.object[0] + ".rotateZ")
# Create expression for VehicleF with a random multiplier added to the expression.
randX = random.uniform(-1,1)
randY = random.uniform(1,-1)

#the first lines define how the agent will wander
expString = "// Set wander motion of vehicle and add random multipliers.\n"
expString += "%s.impulseX" % self.rigid
expString += " = sin(time * %f);\n" % randX
expString += "%s.impulseY" % self.rigid
expString += " = (noise(time) * %f);\n\n" % randY
#the second part, how it rotates according to the direction it is going (velocity vector)
expString += "// Set orientation of Vehicle according to the velocity direction.\n"
expString += "float $fVel[];\n"
expString += "$fVel = `getAttr %s.velocity`;\n\n" % (self.rigid)
expString += "%s.rotateX = 0;\n" % self.object[0]
expString += "%s.rotateZ = atan2d( $fVel[0], $fVel[1] );\n" % (self.object[0])
expString += "%s.rotateY = 0;\n\n" % self.object[0]
#the third part, checking bumps on other agents
expString += "//checking bumps on other agents\n"
expString += "string $lastHit;\n"
expString += "if (%s.contactCount > 0){\n" % self.rigid
expString += " int $contactCount = `getAttr %s.contactCount`;\n" % self.rigid
expString += " $lastHit = `getAttr %s.contactName[0]`;\n" %self.rigid
expString += ' string $rigid = "%s";\n' % self.rigid
expString += ' python("hit(\'"+$lastHit+"\', \'"+ $rigid +"\')");\n'
expString += "};//endif\n"

self.expString = expString
cmds.expression(s=expString)


##############################################
class Crowd:
def __init__(self, numAgents=4, minPosition=-20, maxPosition=20, walls=0):
#set the playback options to increase the time range
cmds.playbackOptions(min= 1, max=5000)
self.numAgents = numAgents
self.minPosition = minPosition
self.maxPosition = maxPosition
#get any selected objects
self.wallObjs = cmds.ls(sl=1)
#create the rigid solver
self.solver = self.createSolver()
#create the agents
self.createAgents()
#create the walls
if walls: self.makeWalls()

def createSolver(self):
solver = cmds.rigidSolver( create=1,
current=1,
name="crowdSolver",
velocityVectorScale=0.5,
displayVelocity=1,
sc=1, #showcollision
ctd=1 #contact data
)
cmds.setAttr(solver + ".allowDisconnection", 1)
return solver

def createAgents(self):
type1 = ["Bacteria", (1,1,1), (1,1,0)] #name, scale, color
type2 = ["Drug", (5,5,5), (.6,.6,.6)]
types = [type1, type2]
self.DrugAgents = []
self.BacteriaAgents = []
for i in range(self.numAgents):
#get the agent type randomly
at = random.choice(types)
#get random x and y
x = random.uniform(self.minPosition,self.maxPosition)
y = random.uniform(self.minPosition,self.maxPosition)
#create the agents
a = Agent(self.solver, at[0], color=at[2], size=at[1], position=(x,y,0))
if at[0] == "Bacteria":
self.BacteriaAgents.append(a)
else:
self.DrugAgents.append(a)

def makeWalls(self):
#get selected object,
#which should be already with its normals facing to the right directions,
#and convert it to passive rigid bodies
if len(self.wallObjs) == 0:
return "No wall objects were selected."
else:
for w in self.wallObjs:
self.wallRigid = cmds.rigidBody(w, passive=1, name= "wall_rigid", bounciness=.8)

########################################
c=Crowd(numAgents=4, walls=1)

Wednesday, July 8, 2009

Assignment 03B - Final

As a continuation of the final assignment, you should now try to script your idea. Most of the ideas posted deal with collisions, and reactions according to those collisions. As this was not part of our original crowd system example given in class, here is an example script which deals with collision detection:

cs_help.py

Here is also an example .mb file where the system above is already placed in the scene:

cs_help.mb

The rule which deals with the collision can be found in the hit function, right in the beginning of the script. this system not perfect, has tons of caveats, but you can get the idea.

In this script you can also see how to create an enclosure for your agents, something such as a box which contains the whole system inside, so that your agents are "trapped".

If you have too much difficulty, post your doubt on the blog. I'll check it daily to answer it!

The deadline for this assignment is this Sunday (12.07).

w08 - script

Here is the finalized script for the crowd system done in the past two classes. It also includes the global forces option in it. For details, read the comments.

crowdSystem.py

Sunday, July 5, 2009

Assignment 03 A - Biennale Self Organization System - Alexandra and Mircea







BACTERIUM WAR



Assignment 03A_Alice



















This is my initial thought...but I am not sure if my scenairo is too complicated. Represented by simple boxes, it is imitating a situation found in a district or shopping mall.


Agent Type A represents poeple in different age groups. Therefore, in general, they are attracted/repulsed to different programmes, with different speeds.


Agent Type B (passive) represents different programmes we can found either on streets or in a shopping mall. I have just named few in the list.


Things to be defined

- Attraction Level i,e the speed and amount

- Attraction Duration i.e. how long will Agent A be attached with Agent B

- Attraction Capacity i.e. repulsion occcurs when some Agent B is over-attracted.


Differen types of Agent A should be generated randomly and being replaced along the timeline.

Assignment 03A Shi xinyu & Liu

Wednesday, July 1, 2009

Agent-based system - applications

Here are some examples of the use and study of agent-based, self-organizing systems in architecture:

02

03 04 05 Capture1

The images above are from the project Swarm Urbanism (2008) from Kokkugia, a speculative proposal which

(...) posits an urban design methodology based on the emergent capacities of Swarm Intelligence in rethinking of the current redevelopment of the Melbourne Docklands. Swarm systems involve the local interaction of autonomous agents, which give rise to emergent behavior and the self-organisation of structures. An application of swarm logic to urbanism enables a shift from notions of the master-plan to that of master-algorithm as an urban design tool. This shift changes the conception of urban design from a sequential set of decisions at reducing scales, to a simultaneous process in which a set of micro or local decisions interact generate a complex urban system. Rather than designing an urban plan that meets a set of criteria, urban imperatives are programmed into a set of agents which are able to self-organise. Consequently this conception of urbanism generates systems that are flexible to respond to the constantly changing political, economic and social pressures of urban development.

a01 a02 a03 a04

Also from Kokkugia, the above project (Emergent Fields, 2003), in which

(...) Agent-based simulation techniques are used to generate programmatic relationships and an architectonic response to this field of program. Architectural elements such as a façade, plaza, or construction grid are assigned rules or behaviours, which govern the way in which they interact with this field in the form making process. This develops an emergent relationship between program and peculiarities of architectural form, enabling the design process, and resultant architecture to exhibit particular behavioural qualities.

Also in the research developed by Space Syntax together with the Space Group at Barttlet, we can find the use of agent-based systems to explore pedestrian behaviour within the field of urbanism, flight-routes, programmatic organization, etc.

Space syntax has found that, despite many proposed higher-level cognitive models, there appears to be a fundamental process that informs human and social usage of an environment. In this paper we describe an exosomatic visual architecture, based on space syntax visibility graphs, giving many agents simultaneous access to the same pre-processed information about the configuration of a space layout. Results of experiments in a simulated retail environment show that a surprisingly simple 'random next step' based rule outperforms a more complex 'destination based' rule in reproducing observed human movement behaviour. We conclude that the effects of spatial configuration on movement patterns that space syntax studies have found are consistent with a model of individual decision behaviour based on the spatial affordances offered by the morphology of the local visual field.

Tuesday, June 23, 2009

Assignment 03A

In the first part of this assignment, you should think about the logic of a self-organizing system. You should draw diagrams and write the whole logic by which it would work. Here are some guidelines:

  • Think about local intelligence and local interactions. Each agent will only "look" at its immediate surroundings and make decisions based on these "encounters". The collective intelligence comes from these local interactions (think ant colonies!)
  • Define roles of your agents, or types of agents. Each agent has a set of properties and will react in a certain way when encountering certain other agents. Keep in mind the exponential complexity here: for each agent you should define the action to be taken when it encounters each of the other agents and also agents of the same type (in case there is more than one). So if you have 4 types of agents, you have to think of circa 16 types of interactions
  • Think also of passive agents. Obstacles, for example, could be characterized as passive agents: they affect all other agents, but it doesn't react on any way.
  • Think of forces of attraction and repulsion, and also on other more complex arrangements (in case one agent encounter a group of other agents combined, for example)

More important, use your imagination. Produce material which could explain for ANYONE about your idea, and post on the blog. Be as thorough as possible!

Please post all until Sunday, so you can have it out of the way the following week, and I can use the other week to prepare some help for you!

w07 - recap + script

Yesterday we started looking at our third and final topic: self-organizing systems and dynamics/expressions in Maya. We started some simple crowd system class, and saw some principles of dynamics in Maya (rigid bodies) and expressions (to make objects move).

Here is the script until the part we accomplish together yesterday:

crowdSystem_w07.py

In the next class we should finish it by applying fields forces (for attraction and repulsion between elements) and create the desired number of leaders and followers, connecting their dynamic forces to make them interact with each other.

Sunday, June 21, 2009

Delaunay Triangulation via Math

Here is what was supposed to be your assignment 02B, a class definition to calculate Delaunay triangulations from a set of points by means of mathematical calculations (without the help from Qhull).

delaunay.py

There are several algorithms to approach such problem, some more efficient than others. This seems to be one of the simplest, and this class definition is based on it.

Take some time to study it and check if you understand how it is done. I'll talk about it shortly on next class.

Wednesday, June 17, 2009

w06 - recap and script

Last class we saw how to parse a Delaunay 2D text file generated by qhull and convert it to objects in Maya's stage. Here is the link from the finished script, which also contains the Delaunay3D and ConvexHull classes:

qhull_w06.py

Sunday, June 14, 2009

I'm not stupid :-)




import maya.cmds as cmds

def IsBounded(item):
for x in item:
if x < 0:
return False
return True

class delauney:
def __init__(self):
self.vertices = []
self.regions = []
self.dimension = ""
self.path = "C:/MAYA/"
print "Instance of class Delauney created."

def load(self):
# Get vertices positions in the points.txt

print "Loading Qhull file..."
# Open the file and get the second line in order to get the number of vertices
f = open('C:/MAYA/points.txt', 'r')
d = f.readline()
i = f.readline()
i = int(i.strip())

# Get line by line the x, y positions (and z if it exists)
while i > 0:
l = f.readline()
t = l.split()
pt1 = float(t[0])
pt2 = float(t[1])
if len(t) > 2:
pt3 = float(t[2])
self.dimension = "3D"
self.vertices.append([pt1, pt2, pt3])

else:
pt3 = 0
self.dimension = "2D"
self.vertices.append([pt1, pt2])
i = i-1

# Feedback
print ">>> RESULTS"
print len(self.vertices), " vertices ", self.vertices

# Open the qHullResults.txt in order to get the name of the points to join.
# Get the first number, in order to get number of regions
# Daniel, I'm sorry for the hardcoding for the names of the files, and for the "region.append(int(t[2]))" if its not a 3D drawing, but i'm really tired
f = open('C:/MAYA/qHullResults.txt', 'r')
l = f.readline()
i = int(l)

# Get line by line the name of the points to join
while i > 0:
l = f.readline()
t = l.split()
region = []
j=0
while j < i:
region.append(int(t[0]))
region.append(int(t[1]))
region.append(int(t[2]))
j = j + 1
self.regions.append(region)
i = i-1

# Feedback
print len(self.regions), " regions ", self.regions
f.close()

def draw(self):
# draw a curve between the points to create the regions!

for region in filter(IsBounded, self.regions):
vs = []
neg = 0

for i in region:
if i < 0:
neg = 1
break

v = self.vertices[i]
vs.append(v)

if neg == 0:
crv = cmds.curve(ep=vs, d=1)
cmds.closeCurve(crv, rpo=1)