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)

No comments:

Post a Comment