Tutorial on Processing: beginShape, endShape, mouseDragged, function, class These two examples demonstrate the Processing facilities for drawing 3D geometric shapes and building up more complex applications through the use of function definition and class definitions. Fixed tetrahedron My first sketch was to build a tetrahedron: a 4 sided polyhedron in which each face is a triangle. A tetrahedron is defined by its 4 vertices. The beginShape and endShape functions are used to draw the faces in space. I use the mouseDragged function in a way demonstrated on the Processing.org site to allow the viewer to rotate around the X and Y axes to display the shapes from different angles. This tetrahedron has one face on the xy plane consisting of a triangle of 3 equal sides, angle 60 degrees. Since Processing uses radians, I define a variable rad60 to use. This first figure shows the first face. Y Z X The tetrahedron other 3 faces each are based the sides of this triangle reaching 'up' to a point above the middle of the first face. The next figure is a very rough sketch. Y Z X The global variables used are float side = 100; float rad60=60*PI/180; // radian value for 60 degrees float rotx = PI/4; // arbitrary initial value float roty = PI/4; //arbitrary initial value The sketch has 4 functions: definitions for the defined functions setup, draw and mouseDragged, and one totally defined by me, the programmer: drawtetrahedron. The Processing specified functions are: void setup() { size(800,600,P3D); } void draw() { background(0); translate(width/2.0, height/2.0, -100); rotateX(rotx); rotateY(roty); drawtetrahedron(); } void mouseDragged() { float rate = 0.01; rotx += (pmouseY-mouseY) * rate; roty += (mouseX-pmouseX) * rate; } The second example will make drawtetrahedron take parameters and produce any tetrahedron. The first example draws one specific tetrahedron. void drawtetrahedron() { beginShape(TRIANGLES); vertex(-side/2,0,0); vertex(0,sin(rad60)*(-side),0); vertex(side/2,0,0); endShape(); beginShape(TRIANGLES); vertex(-side/2,0,0); vertex(0,sin(rad60)*(-side)*.5,sin(rad60)*(side)); vertex(side/2,0,0); endShape(); beginShape(TRIANGLES); vertex(-side/2,0,0); vertex(0,sin(rad60)*(-side)*.5,sin(rad60)*(side)); vertex(0,sin(rad60)*(-side),0); endShape(); beginShape(TRIANGLES); vertex(0,sin(rad60)*(-side),0); vertex(0,sin(rad60)*(-side)*.5,sin(rad60)*(side)); vertex(side/2,0,0); endShape(); } Notice that this function draws 4 shapes based on fixed values, since the variables side and rad60 do not change. The default fill and stroke produce white triangles with black outlines. The effect of these functions is to re-draw the tetrahedron each frame, changing the rotation based on the values of rotx and roty. Exercises: 1. Change the sketch to rotate around the Y and Z axes. 2. Isolate the rotation to be just around 1 axis, say the X axis. You do this by commenting out the line changing roty. 3. Insert a println statement in the mouseDragged function to display the changed values of rotx and roty. To make these numbers more understandable, convert them from radians to degrees. General tetrahedron function The challenge I set myself for the second example was to write a function that would be passed parameters specifying the specific tetrahedron. What defines a tetrahedron? Answer: 4 points in space. I decided to define a class named Pt. It would contain 3 attributes (3 object variables): x, y, and z. This meant that I would 'send' the drawtetrahedron function 4 variables as opposed to 4 times 3. The Pt class is defined as follows: class Pt { float x,y,z; Pt (float xx,float yy,float zz) { x = xx; y = yy; z = zz; } } I then decided to make the fill color also be specified in the function. This meant the function would take 3 more parameters: the Red color, Green color, and Blue color values. The sketch demonstrating the general drawtetrahedron function shows 2 tetrahedrons: one is the same as in the first sketch. In addition to the 4 global variables in the first sketch, this sketch has 8 variables of datatype Pt. Pt p1 = new Pt(-side/2,0,0); Pt p2 = new Pt(0,sin(rad60)*(-side),0); Pt p3 = new Pt(side/2,0,0); Pt p4 = new Pt(0,sin(rad60)*(-side)*.5,sin(rad60)*(side)); Pt p5 = new Pt(side,0,0); Pt p6 = new Pt(side*1.5,sin(rad60)*side,0); Pt p7 = new Pt(2*side,0,0); Pt p8 = new Pt(side*1.5,sin(rad60)*side*.5,sin(rad60)*side); The setup and the mouseDragged function are the same as in the first sketch. The draw function is similar: it includes 2 calls to the new drawtetrahedron function and makes use of the p1 through p8 variables: void draw() { background(0); translate(width/2.0, height/2.0, -100); rotateX(rotx); rotateY(roty); drawtetrahedron(230,0,0,p1,p2,p3,p4); drawtetrahedron(100,0,100,p5,p6,p7,p8); } The drawtetrahedron function looks about the same as the first one. It has a more complex header line because of the parameters. The calls to vertex look simpler because they invoke the passed Pt variables. void drawtetrahedron(int colR, int colG, int colB,Pt t1,Pt t2, Pt t3, Pt t4) { fill(colR,colG,colB); beginShape(TRIANGLES); vertex(t1.x,t1.y,t1.z); vertex(t2.x,t2.y,t2.z); vertex(t3.x,t3.y,t3.z); endShape(); beginShape(TRIANGLES); vertex(t1.x,t1.y,t1.z); vertex(t4.x,t4.y,t4.z); vertex(t3.x,t3.y,t3.z); endShape(); beginShape(TRIANGLES); vertex(t1.x,t1.y,t1.z); vertex(t4.x,t4.y,t4.z); vertex(t2.x,t2.y,t2.z); endShape(); beginShape(TRIANGLES); vertex(t2.x,t2.y,t2.z); vertex(t4.x,t4.y,t4.z); vertex(t3.x,t3.y,t3.z); endShape(); } Exercises 1. Change the sketch to draw 3 parallel tetrahedrons, all lining up on the x axis. 2. Change the sketch to draw a tetrahedron based on the xz plane. 3. Change the sketch to draw one tetrahedron inside the other.