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!
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:
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.
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).
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.
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:
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])
# 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)
Saturday, June 13, 2009
this is my studio script (using classes). i wrote some more helping scripts in the beginning.
in the maya scene should be a few locators (which are attraction and repulsion points)
import maya.cmds as cmds import maya.mel as mm import math import sys from random import* from setColor import* sys.setrecursionlimit(8000)
def centerOfFace(facet): #find the vertices that define that face. vertex = cmds.polyListComponentConversion(facet, ff=1, tv=1) cmds.select(vertex, r=1) vertexFlat = cmds.ls(sl=1, fl=1)
#find out how many vertices define that face vertCount = len(vertexFlat) #print vertexFlat
#for each vertex go through and find it's world space position. vertPositionSumX = 0. vertPositionSumY = 0. vertPositionSumZ = 0. for a in range(0, vertCount, 1): coordinate = cmds.pointPosition(vertexFlat[a], w=1) vertPositionSumX += coordinate[0] vertPositionSumY += coordinate[1] vertPositionSumZ += coordinate[2]
def direction(a,b): "Returns the direction vector going from a to b" # Calculate direction vector dire = [ a[0] - b[0], a[1] - b[1], a[2] - b[2] ] # a-b return dire
locs =[] for i in range (AmountOfAttractors): L = repulciveLocs[0] repulciveLocs.remove (L) locs.append (L) return locs, repulciveLocs
def polyCubesInLocators (self, locators, size): cubes = [] for i in locators: position = cmds.pointPosition(i) cube = cmds.polyCube (w =size ,h=size ,d=size ) cmds.move (position[0], position[1], position[2], cube) cubes.append (cube)
return cubes
def makeNet (self, locators, numRow, numCell): allLocs = [] startLocs = [] x = randint (98,102) x = x/100.0 for i in range (numRow): for j in range (numCell): newloc= cmds.spaceLocator( p=(j*10*x, i*10*x, 0) ) if i == 0: startLocs.append (newloc) elif i == (numRow-1): startLocs.append (newloc) else: allLocs.append (newloc) cmds.refresh() return startLocs, allLocs
def changeNetBecauseRepulsive (self, allLocs, repulsiveLocs, repSize, pointsAmount = 4, N=0): Empty =[] LOCS = allLocs for i in allLocs: Empty.append (i) C = pointsAmount
for k in repulsiveLocs: for i in range (repSize): L=(repSize/5)*(i+1) for j in range (L): Kpos = cmds.pointPosition(k) closLoc = closestLocatorToPoint(Kpos, LOCS) LOCpos = closLoc[1] clLoc = closLoc[0] direc = direction(LOCpos, Kpos) newX = ((direc[0]*6)/((i+1)*(i+1))) newY = ((direc[1]*6)/((i+1)*(i+1))) newZ = ((direc[2]*6)/((i+1)*(i+1))) cmds.move (newX, newY, newZ, clLoc) LOCS.remove (clLoc)
cmds.refresh() return Empty
def subdivStartLocs (self, startLocs, locs): subStartLocs = [] lenLocs = len(locs) lenStertLocs = len(startLocs) locsPerUnit = lenStertLocs/lenLocs for i in range (lenLocs): groupOfLocs = [] groupOfLocs.append (locs[i]) for j in range (locsPerUnit): numOfLoc = i*locsPerUnit+j loccc = startLocs [numOfLoc] loccc = loccc[0] groupOfLocs.append (loccc) subStartLocs.append (groupOfLocs)
return subStartLocs
def looping1 (self, subdivStartLocs, allLocs, locs, size, number, cubes): #cmds.pause( sec=0.5 ) cmds.refresh() size *= 1.03 color = 255/(size*10) number = number + 1 print "number" print number temploryList = [] midPoints =[] N=0 for i in subdivStartLocs: if number == 1: Pt1 = len(i)/2 midP = i[Pt1] midP = cmds.pointPosition(midP) remLocs = [] remLocs.append (i[0]) x = randint (2,len(i)+7) else: midP = i remLocs = [] #remLocs.append (i) x = randint (2,len(subdivStartLocs)+7) n = 0 if len(allLocs)>x: for g in range (x): closLocData = closestLocatorToPoint (midP, allLocs) closLocator = closLocData[0] closLocPos = closLocData[1] closLocDist = closLocData[2]
In this assignment you should take a look at the script from last class and try to write it further. The idea is to create a new class definition on it, either to produce Delaunay triangulations or convex hulls. Here are some tips:
The qhull commands you need to run are already in the runQhull method of the Qhull class. You don't need to worry about them. They will return you a text file containing all the information you need to assemble your objects
The structure of the new class should be very similar from the Voronoi class structure. You should write a load method to read the file you generated from qhull and parse it, saving vertex and region information on the regions and vertices attributes of the class.
Then you should then concentrate on the draw function. Keep in mind some of the workarounds done in the Voronoi class, like re-ordering the vertices, are not necessary in the Delaunay or convex hull. Just read all the vertices, then draw the regions using the vertices indexes.
Here is a link to download the working script from last class, which already contains the new voronoiShatter method. It is entirely commented and you should be able to understand it from what was explained in class.
On this class we took a look on all the functions contained in the voronoi script we are working on: point generation function, qhull commands, voronoi creation. We also wrote our own voronoi shatter method to the voronoi class, going through concepts of vector math along the way.
In our class tomorrow we will take a close look at a ready-made script containing advanced methods for the generation of Voronoi diagrams using Qhull.
After that, we will add one more method to the class, which uses pure mathematics to perform voronoi calculations, so we can learn a bit about vector math and some other scripting techniques.
For that, you should download this script and save it in your script folder.