Archive for April, 2009

Adding Per Particle Script to Maya Particles via MEL

Wednesday, April 29th, 2009

A friend of mine was wondering about how to attach per particle expressions to particles via mel

so I wrote this script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
global proc int doesPPVectorAttrExist( string $attrName, string $particleShape)
{
	//We check to see if the PP attribute is here
	string $allPPVectors[] = `particle -q -perParticleVector $particleShape`;
	for ($i in $allPPVectors)
		{
			if ($i == $attrName)
			{
				return 1;
			}
		}
		return 0;
}
 
global proc string myFancyParticles( string $inputShapeNode, string $particleSystemName)
{
	string $returnValue = "Success";
	string $namesOfShapeNodes[] = `ls $inputShapeNode`;
	if (size($namesOfShapeNodes) > 0)
	{
		//Create a new particle system using the name entered into the function, use the first occurance inputShapeNode as the emmitter
		string $newParticles[] = `particle -n ($particleSystemName) -sn ($namesOfShapeNodes[0])`;
		//this returns an array, first entry is the transform, second is the shape node
		string $particleTransform = $newParticles[0];
		//the shape node may already exist multiple times, so using ls we get the all of them
		string $allParticleShapes[] = `ls $newParticles[1]`;
 
		int $lastEntry = size($allParticleShapes) - 1;
		//this is a trick to get the length of the array
		string $currentParticleShape = $allParticleShapes[$lastEntry];
		//now we have the lastEntry in the array
		if (doesPPVectorAttrExist("rgbPP",$currentParticleShape)//See procedure above)
		{
			//If the Per particle attribute exists our work is done
			print "rgbPP found!!!";
		}
		else
		{
			//Because the Per Particle Attribute Doesnt exist, we have to make ie
			print "No rgbPP here!!!, Lets add it!\n";
			//Adding a attribute is pretty straight forward
			addAttr -ln rgbPP -dt vectorArray $currentParticleShape;
			//Initialise the array to white
			setParticleAttr -at rgbPP -vv 1 1 1 $currentParticleShape;
			if (doesPPVectorAttrExist("rgbPP",$currentParticleShape))
			{
				print "rgbPP added all is well!!!\n";
			}
 
		}
		//Now bang on the particle expression! as a runtime before dynamics
		dynExpression -rbd -s "rgbPP = rgbPP * .9;" $currentParticleShape;
	}
	else
	{
		$returnValue = "Failure";
	}
	return $returnValue;
 
}

So if you want to test it out

Save it to a location like

/home/samh/exampleScriptingParticles.mel

Then you can try it out with the follow mel snippet in the script window

1
2
3
4
source "/home/samh/exampleScriptingParticles.mel"; //Update the script
file -f -new; //Emptry file
polySphere; //Create pSphereShape1
myFancyParticles( "pSphereShape1", "dustSphere"); //Call the function

Grey Scale Stenciling Step by Step

Thursday, April 23rd, 2009

Start by selecting a source image

banana

This one was found on google images by searching for banana

Open the image in GIMP/Photoshop etc

Crop to 4:3

Resize to 160×120 or 120×160

Change the colour from RGB to greyscale

It should look like this now

banana_greyscale160x120

Change the colour from greyscale to indexed colour, choose, 8 colours and dithering turned on

It should look like this

banana_8colour

This is where it gets a little tricky

for each colour of grey we want to make a square of increasing size to show how dark it is

I have written a little program that does this,if you really want I can do this step for you

see the previous post

here is the output as a PNG and PDF

banana

PNG

PDF of Banana all filled in

The trick is now to enlarge this image to be as big as your canvas

There is a neat tool called “Poster” which is part of Linux UI package KDE, if you arent familar with command line tools the stuff below will seem like it is in a foreign language

Usage: poster  infile

options are:
   -v:         be verbose
   -f:         ask manual feed on plotting/printing device
   -i:    specify input image size
   -c: horizontal and vertical cutmargin
   -w: horizontal and vertical additional white margin
   -m:    media paper size
   -p:    output poster size
   -s: linear scale factor for poster
   -o:   output redirection to named file

   At least one of -s -p -m is mandatory, and don't give both -s and -p
    is like 'A4', '3x3letter', '10x25cm', '200x200+10,10p'
    is either a simple  or %

   Defaults are: '-mA4', '-c5%', '-i' read from input file.
                 and output written to stdout.

So with a bit of luck you can get this to produce say a 4×4 grid of a4 sheets that you can print on a standard laser or inkjet

I have attached the sample PDF for the bananas

Feel free to print out 18 pages : PDF of the tiles of the poster

Using the grid references in the corner you can arrange the tiles

crosshairandgridref

the little cross hairs will help you line it all up

If you wanted to cheat you could use this for paste ups

But if you want stencils then is the labourious bit

Printing onto transperancies, cutting out all the squares

If you made a tool of each square size as a punch you could save some time

Then spraying aerosol enamel paint through the squares onto canvas or whatever

You get too cut out 19200 squares, woo hoo!

Half tone stencilling with 30% less repeditive strain injury

Wednesday, April 15th, 2009

The process I came up with is pretty straight forward

  1. get an image
  2. crop to 4:3 or any other neat golden mean which you can find a canvas for
  3. reduce to a small number of pixels, I used 160x120px
  4. drop to greyscale
  5. 8 colour palette using dithering
  6. save as gif
  7. run it through program below to make a black square for each pixel
  8. convert SVG to PostScript
  9. use Poster to blow it up to 4×4 A4 sheets to the size of your canvas
  10. Print to overhead transperancys, you will get registration points and numbering of the tiles
  11. cut out all the squares to make stencils
  12. apply black enamel paint to white canvas
  13. enjoy the analog digital fusion
  14. 160×120 pixels means you have to cut out 19200 little squares

Another idea would be to get 8 hole punches and change the code below to indicate what radius hole punch to use

that would cut down on the rsi by at least 80%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
"""\
SVG.py - Construct/display SVG scenes.
 
The following code is a lightweight wrapper around SVG files. The metaphor
is to construct a scene, add objects to it, and then write it to a file
to display it.
 
This program uses ImageMagick to display the SVG files. ImageMagick also
does a remarkable job of converting SVG files into other formats.
"""
import math
import os
 
from PIL import Image
 
display_prog = 'display' # Command to execute to display images.
 
class Scene:
	def __init__(self,name="svg",height=400,width=400):
		self.name = name
		self.items = []
		self.height = height
		self.width = width
		return
 
	def add(self,item): self.items.append(item)
 
	def strarray(self):
		var = ["<?xml version=\"1.0\"?>\n",
			   "<svg height=\"%d\" width=\"%d\" >\n" % (self.height,self.width),
			   " <g style=\"fill-opacity:1.0; stroke:none;\n",
			   "  stroke-width:0;\">\n"]
		for item in self.items: var += item.strarray()
		var += [" </g>\n</svg>\n"]
		return var
 
	def write_svg(self,filename=None):
		if filename:
			self.svgname = filename
		else:
			self.svgname = self.name + ".svg"
		file = open(self.svgname,'w')
		file.writelines(self.strarray())
		file.close()
		return
 
	def display(self,prog=display_prog):
		os.system("%s %s" % (prog,self.svgname))
		return
 
 
class Line:
	def __init__(self,start,end):
		self.start = start #xy tuple
		self.end = end	 #xy tuple
		return
 
	def strarray(self):
		return ["  <line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" />\n" %\
				(self.start[0],self.start[1],self.end[0],self.end[1])]
 
 
class Circle:
	def __init__(self,center,radius,color):
		self.center = center #xy tuple
		self.radius = radius #xy tuple
		self.color = color   #rgb tuple in range(0,256)
		return
 
	def strarray(self):
		return ["  <circle cx=\"%d\" cy=\"%d\" r=\"%04f\"\n" %\
				(self.center[0],self.center[1],self.radius),
				"	style=\"fill:%s;\"  />\n" % colorstr(self.color)]
 
class Rectangle:
	def __init__(self,origin,height,width,color):
		self.origin = origin
		self.height = height
		self.width = width
		self.color = color
		return
 
	def strarray(self):
		return ["  <rect x=\"%04f\" y=\"%04f\" height=\"%04f\"\n" %\
				(float(self.origin[0]),float(self.origin[1]),float(self.height)),
				"	width=\"%d\" style=\"fill:%s;\" />\n" %\
				(self.width,colorstr(self.color))]
 
class Text:
	def __init__(self,origin,text,size=24):
		self.origin = origin
		self.text = text
		self.size = size
		return
 
	def strarray(self):
		return ["  <text x=\"%d\" y=\"%d\" font-size=\"%d\">\n" %\
				(self.origin[0],self.origin[1],self.size),
				"   %s\n" % self.text,
				"  </text>\n"]
 
 
def colorstr(rgb): return "#%x%x%x" % (rgb[0]/16,rgb[1]/16,rgb[2]/16)
 
def test():
	curImage = Image.open("/home/samh/input.gif")
	dimensions = curImage.size
 
	#print dimensions
	scale = 20.0
	scene = Scene('test',dimensions[1]*scale,dimensions[0]*scale)
	paletteSize = 8.0#len(curImage.palette.palette)/len(curImage.palette.getdata()[0])
	for row in range(dimensions[0]):
		for column in range(dimensions[1]):
			size = math.pow( (1 - float(curImage.getpixel((row,column)))/float(paletteSize))*2,0.5) * scale
			dimension = scale/float(paletteSize) * size
			black  = (0,0,0)
			bottomRight = (row*scale,column*scale)
			scene.add(Rectangle(bottomRight,dimension/5.0,dimension/5.0,black))
	scene.write_svg(filename="test.svg")
	scene.display(prog="inkscape")
	return
 
if __name__ == '__main__': test()