Introduction
Processing4Net is a simple ASP.NET wrapper around processing.js, a port of the processing programming
language to JavaScript made by John Resig back in 2008. Processing is a programming language created by Casey Reas and Benjamin Fry for the electronic arts and visual design communities.
Processing was initially developed to serve as a software sketchbook and to teach fundamentals of computer programming within a visual context.
Since then Processing has evolved into a tool for generating finished professional work, and these days there are tens of thousands of artists, designers,
researchers, students, and hobbyists who use Processing for learning, prototyping, and production.
I first came across the Processing project a couple of years ago, and found it to be an excellent tool for creating pleasing graphics that punched a lot of power.
The image above is from Exit, a half-hour immersive visualization of human migration data is an excellent example of how powerful the full Processing
system can be: http://stewd.io/w/exit/
Processing is a programming language designed to make it easy to create images, animations and interactions. The idea behind Processing was to create something that allowed students to learn programming using a tool that provided instant gratification. Add a line of code and a circle shows up on the screen, add a few more lines and the circle follows the mouse, then change the color of the circle by adding just a few more lines of code.
This was called sketching with code, and a program written in Processing is often called a sketch.
While the Processing is based on Java, Processing.js allows Processing
code to be run by any HTML5 compatible browser, including current versions of Firefox, Safari, Chrome, Opera, and Internet Explorer. Even if Processing.js
has a few limitations compared to its sibling project, it’s still one of the most powerful HTML5 based environments for graphics programming.
Below is a screenshot of the classic asteroids game, by Benjamin Blundell, implemented using processing.js.
Processing4Net implementation
As of this writing, the current version of processing.js is 1.3.6 and hence Processing4Net is an implementation of an ASP.NET server control
that allows us to easily embed processing files (*.pde) on our web pages. The idea is that it would be kind of nice to write something as simple as:
<cc1:Processing ID="Processing1" runat="server" Sources="curves11.pde">
</cc1:Processing>
when we want to add processing.js functionality to our page – without having to think about the canvas or the JavaScript stuff.
It turns out that creating an ASP.NET server control for processing.js is pretty easy as long as all we want is to load a Processing file into the browser.
First we create a c# class library called Processing4Net, and then we create our control called Processing.
[ToolboxData(@"<{0}:Processing runat=""server"" > </{0}:Processing>")]
public class Processing : Panel
{
}
I chose to derive Processing control from Panel, but don’t treat it as a fully functional panel yet, as child controls will not be handled correctly.
The ToolboxData attribute defines the markup code that will be added to an ASP.NET page when you drop the control on the page’s design surface. Next we need a property for the Processing file:
[
Bindable(true),
DefaultValue("")
]
public String Sources
{
get
{
return ToString(ViewState["data-processing-sources"]);
}
set
{
ViewState["data-processing-sources"] = value;
}
}
Now we need to add processing-1.3.6.js to the root of the project, and set the ‘Build Action’ to ‘Embedded Resource’.
The next thing to do is to open AssemblyInfo.cs, in the properties folder of the project, and add two attributes:
[assembly: WebResource("Processing4Net.processing-1.3.6.js", "text/javascript")]
[assembly: ScriptResource("Processing4Net.processing-1.3.6.js", "Processing4Net.Processing", "Processing4Net.Resource")]
This defines the JavaScript file as a Web Resource allowing the WebResource.axd HttpHandler to work in conjunction with the ClientScriptManager class
to dynamically output the embedded resource, making it accessible from <script …> tags on the client.
Now we are ready to register the script with the ClientScriptManager of the page, which we perform during the pre-render stage of the control.
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
string resourceName = "Processing4Net.processing-1.3.6.js";
ClientScriptManager cs = this.Page.ClientScript;
cs.RegisterClientScriptResource(typeof(Processing4Net.Processing), resourceName);
}
All that’s left is to add the canvas to the page:
protected override void RenderChildren(HtmlTextWriter writer)
{
if (DesignMode == false)
{
string sources = Sources;
sources = this.Page.ResolveClientUrl(sources);
writer.Write("<canvas data-processing-sources=\"" +
sources + "\"></canvas>");
}
base.RenderChildren(writer);
}
That’s really all that’s required to implement the ASP.NET server control for processing.js and we are now ready to create beautiful,
interactive, visualizations using the Processing programming language.
A very short introduction to processing.js
Included with the source code for the project is a small ASP.NET web application that allows you to create an infinite number of more or less pleasing visualizations.
All the images at the top of this article were generated by this application, so feel free to release the random artist inside you.
If you take it for a spin you’ll notice that you can alter a visualization by dragging the mouse across its surface – and you’ll hopefully also notice that transitions are animated.
First we define the setup() function. This function is called once when the program is started. This is where we define initial environment properties
such as screen size, background color, loading images, etc. before the draw() begins executing. There can only be one setup() function for
each Processing program and it should not be called again after its initial execution.
void setup()
{
size(600,600);
smooth();
frameRate(24);
initialize();
}
So the size of this visualization will be 600 by 600 pixels, smooth() tells processing to use anti-aliased drawing, and frameRate(24) specifies
the number of frames to be displayed every second. If the processor is not fast enough to maintain the specified rate, it will not be achieved. Our initialize() function looks like:
void initialize()
{
if (frequency.random)
{
fx = (int) random(frequency.x.min,frequency.x.max);
fy = (int) random(frequency.y.min,frequency.y.max);
phix = (int) random(frequency.phase_x.min,frequency.phase_x.max);
phiy = (int) random(frequency.phase_y.min,frequency.phase_y.max);
}
else
{
fx = (int) frequency.x.value;
fy = (int) frequency.y.value;
phix = (int) frequency.phase_x.value;
phiy = (int) frequency.phase_y.value;
}
if (modulation.random)
{
mfx = (int) random(modulation.x.min,modulation.x.max);
mfy = 0;
}
else
{
mfx = (int) modulation.x.value;
mfy = (int) modulation.y.value;
}
numberOfPoints = (int) random(200,1000);
span = random(numberOfPoints*0.4,numberOfPoints*0.9);
r = random(width/4,width/2);
b = (int)random(60);
factor = width*(random(0.25,0.375));
points = new PVector[numberOfPoints];
for (int p = 0; p <= numberOfPoints; p++)
{
PVector l = calculateLissajousPoint(p);
points[p] = new AnimatedPoint(l.x,l.y,l.z);
}
backgroundColor = color(0,0,0);
lissajousColor = color(random(100,255),random(100,255),random(100,255));
noFill();
}
initialize() sets up global variables for our visualization that will later be used by our draw function:
void draw()
{
for (int i=0; i<=numberOfPoints; i++)
{
points[i].animate();
}
background(backgroundColor);
stroke(lissajousColor);
strokeWeight(1);
beginShape();
for (int i=0; i<=numberOfPoints; i++)
{
float d = PVector.dist(points[i].position, new PVector(width/2.0,height/2.0));
float a = pow(1/(d/r+1), 3);
stroke(lissajousColor,a*255);
vertex(points[i].position.x, points[i].position.y);
}
endShape();
for (int i = 0; i < span; i++)
{
int i1 = (int) i;
int i2 = (int)((i1+span)%numberOfPoints);
int c1 = (int) ((i1+b)%numberOfPoints);
int c2 = (int) ((i2+b)%numberOfPoints);
float d = PVector.dist(points[i1].position, points[i2].position);
float a = pow(1/(d/r+1), 3);
stroke(lissajousColor,a*255);
strokeWeight((i/span)*2);
bezier(points[i1].position.x, points[i1].position.y,points[c1].position.x,
points[c1].position.y, points[i2].position.x, points[i2].position.y,
points[c2].position.x, points[c2].position.y);
}
}
This Processing script goes a bit beyond the usual hello world program, but then the visualization is perhaps a bit more interesting.
History
- 4th of June 2012 – Initial posting.