Tutorial for Processing 3D: beginShape, endShape, vertex, texture

advertisement
Tutorial for Processing 3D: beginShape, endShape,
vertex, texture, millis
The Processing language supports creations of surfaces with texture provided by images.
These textured surfaces can be rotated, displayed in different ways, by rotating the axes. I
use the mouse coordinates when the mouse button is pressed to specify the amount of the
rotation. In order to restore the original orientation of the axes, I arranged to check for a
timing delay: if no mouse pressed has happened after a set amount of time, the original
orientation of the axes is restored. The millis function returns the number of milliseconds
since the start of the running of a sketch. This application demonstrates these features.
The image below shows the opening display screen.
The screen shows 4 shapes, 3 vertical walls with texture from an image called fruits and
one oriented horizontally with texture from an image called ground. The back wall has
the image elongated to fit its area.
The next screen shot shows the shape rotated after I have clicked the mouse.
The coordinates of the mouse when pressed is used to calculate values for the rotations
around the X axis and around the Y axis. Each iteration of draw rotates the virtual world
around the x-axis and around the y-axis. When the system detects no mouse presses for a
certain interval of time, the rotation values are reset to zero.
I encourage readers to experiment with the values of the 4 shapes and the expression for
the rotations to gain familiarity with the 3D space.
Shape and texture
Textures are applied to shapes. The texture function takes as its argument a PImage. The
PImage datatype has been shown in previous tutorials. The coding involves a declaration
statement and an assignment statement:
PImage fruit;
fruit = loadImage("fruit.jpg");
[See also createImage.]
Use the Sketch/Add file…. to move a copy of the image file to the data folder within the
sketch folder.
This sketch has two textures, fruit and ground and so I needed to do the coding and
adding the file for each one.
Shapes are set up using the beginShape and endShape commands. There are different
modes for shapes. This application uses the default mode: no arguments for beginShape
or endShape. Between the calls to beginShape and endShape, I coded a call to texture to
specify the texture for the shape, and then 4 calls to vertex, thus specifying a rectangle in
space. A call to vertex: vertex(x,y,z,u,v)
specifies a point in 3D, x, y, z, and a point in the 2D image, u,v. The Processing system
interpolates between these points. What I coded was pretty straight-forward: the upper
left corner of the image is to be mapped to (think of it as tacking on) the upper left corner
of the shape; the upper right corner of the image is to be mapped to the upper right corner
of the shape, and so on.
Rotating around an axis
Processing 3D sets up a virtual world defined by x, y, and z coordinates. The x axis
default position starts at the upper left corner and increasing moving horizontally. The y
axis starts at the upper left corner and increases moving up vertically. The z axis starts at
the upper left corner and moves away from the viewer. The display is defined in terms of
many factors, including a camera position, type of projection (perspetive), focal point,
and lights. This sketch only changes to orientation of the virtual world by rotating the x
and y axes.
Rotating the world around the x axis has the appearance of tipping the shape as shown in
the screen shot.
Similarly, rotating the world around the y axis, turns the shape around.
Each mouse click specifies settings for x and y rotations. The following screen shot
shows significant rotations in both axes:
The most intuitive way to turn mouse clicks into rotations is subject to debate. Processing
supplies the mousePress() function that is invoked each time the mouse button is pressed.
Processing also supplies a function called map that converts numbers from one range of
values to another. This means that a value between 0 and width, say, that would be the
range of mouseX, can be translated into a value from –PI to PI. In the radian system of
angles, PI is what we call doing a 180, a U turn and –PI and PI would leave the
coordinates in the same state. I chose to make the mouseX position map to -PI to PI and
make this change the Y rotation. I mapped to mouseY position to map to PI to –PI (note
the sign change) and make this change the rotation around X. This made a click on the
upper part of the screen push the object back into the screen and a click on the right side
of the display screen push the right side back. I include in the code a println command to
display the rotX and rotY values. Examine the code and change the numbers and
comment out lines to just change along one or the other dimension to improve your
feeling for the spatial relationships.
The draw function uses background to erase (repaint) the display screen. It invokes
translate to move the coordinates to the middle of the screen:
translate(width/2, height/2);
The width and height are built in variables indicating the width and heighr as specified by
the size call.
The code in the draw function does the two rotations based on the values of two
variables, rotX and rotY. The code draws the shapes. All of this is done each frame. That
is, the shapes do not persist as objects, but are re-drawn each time draw is invoked.
Time delay
After experimenting with the rotations, I realized I needed to get back to the original
orientation. This was a good excuse to see how to handle timing. The millis function
returns the number of milliseconds since the application/applet started. By invoking the
function and saving the time of each invocation, I can write code to calculate if there has
been an interval of at least a specified time since the last mouse press.
A variable last is initialized to millis() in the setup function. A variable rest is set to 3000,
3 seconds. In the mousePressed function,
last = millis();
In the draw function, millis is invoked each time so see if a long enough interval has
passed. The code is
if ((millis()-last)>rest) { }
This means: calculate the difference between now (this is millis()) and last. Is it greater
than rest, the time specified to be long enough? If yes, do something.
Implementing Topsy-turvy fruit
The code for this application requires two image files to be added to the sketch data
folder using Sketch/Add file…
These images were each manipulated to be close to 100 by 100 pixels.
The Sketch includes definitions for the 3 Process defined functions: setup, draw and
mousePressed. The Sketch has 6 global variables.
PImage ground, fruit;
float rotX, rotY;
float last;
float rest;
void setup() {
size(1000,600,P3D);
ground = loadImage("leaves.jpg");
fruit = loadImage("fruit.jpg");
last = millis();
rest = 3000;
frameRate(4);
}
void draw() {
background(255);
translate(width/2, height/2);
if ((millis()-last)>rest) {
rotY = 0;
rotX = 0;
}
rotateY(rotY);
rotateX(rotX);
beginShape();
texture(fruit);
vertex (-100,-100,0,0,0);
vertex (200,-100,0,100,0);
vertex (200,100,0,100,100);
vertex(-100,100,0,0,100);
endShape();
beginShape();
texture(fruit);
vertex (-100,-100,200,0,0);
vertex (-100,-100,0,100,0);
vertex (-100,100,0,100,100);
vertex(-100,100,200,0,100);
endShape();
beginShape();
texture(fruit);
vertex (200,-100,0,0,0);
vertex (200,-100,200,100,0);
vertex (200,100,200,100,100);
vertex(200,100,0,0,100);
endShape();
beginShape();
texture(ground);
vertex (-100,100,0,0,0);
vertex (200,100,0,100,0);
vertex (200,100,200,100,100);
vertex(-100,100,200,0,100);
endShape();
}
void mousePressed() {
rotY =map(mouseX, 0, width, -PI, PI);
rotX =map(mouseY, 0, height, -PI,PI);
println("rotY is "+degrees(rotY)+" rotX is "+degrees(rotX));
last = millis();
}
Exercises
1. Read in the reference section and change the shapes to other modes, such as
TRIANGLES.
2. Change the coding to rotate just around X and then to just around Y. THEN make
the change to toggle between the two by using a variable
boolean changey = true;
When this is true, make the changes for rotY; otherwise, make the change to rotX.
Then change (toggle) changey = !changey
3. You can combine drawing spheres and boxes with shapes. Try it!
.
Download