|
Chapter:
Transforms
pushMatrix() and popMatrix()
As transforms effect everything below their implementation within a
sketch, due to them transforming the entire coordinate system, there
are times when you will find that this is not the effect that you want.
The image below of a cart is made up of three separate images which are
rendered in the following order the wheel in the background, the main
cart and the wheel in the foreground. If our intention was to rotate
the back wheel first, as the back wheel would have to be rendered
before any of the other images, we run the risk of having the
transforms applied to the back wheel effecting the main cart and the
wheel in the foreground as they are rendered after the back wheel, and
will therefore be effected by any scale(), translate() and/or rotate()
function that is intended for the back wheel. This would create the
impression of the cart orbiting around the back wheel, which is
obviously not what we where trying to accomplish. Two functions in
Processing called pushMatrix() and popMatrix() help us to solve this
problem.
The template rendering of the cart.pde sketch
The function pushMatrix() when called before a transform is executed
will store the current state of the coordinate system. This means that
if you call a pushMatrix() function at the start of the draw()
structure it will remember the default position of the coordinate
system (pre-transform). You are then free to apply transforms to the
particular component of the sketch that you would like to scale, rotate
and/or translate. Once you are satisfied with the transforms you have
performed you can then render the component, for example by means of a
call to the image() function. Running the popMatrix() function at this
point will then be necessary to restore the coordinate system back to
the state it was in when the previous pushMatrix() was called. You can
then proceed to run more pushMatrix(), transforms, render, popMatrix()
combinations on other components of the sketch which will remain
unaffected by the previous transforms. Using pushMatrix() and
popMatrix() in this way allows us to apply multiple transforms to a
component of a sketch ,and not have those transforms effect other
components.
Lets have a look at how to use this technique to make the cart move
across the Display Window and have the wheels of the cart rotate
accordingly.
We'll start as always with a template of what we want the final result
should look like:
PImage cart;
PImage wheelFd;
PImage wheelBd;
PImage grass;
void setup(){
size(800,600);
cart = loadImage("cartMain.png");
wheelFd = loadImage("wheelFd.png");
wheelBd = loadImage("wheelBd.png");
grass = loadImage("grassLessBlur.jpg");
}
void draw(){
background(grass);
imageMode(CENTER);
image(wheelBd, -75, 25);
image(cart, 0, 0);
image(wheelFd, -95, 35);
//println(mouseY);
}
Out of interest you might be wondering how the X and Y parameters of
the image() functions which render the wheels relative to the position
of the cart were determined. If you look at the last line you'll see a
println() function that has been commented out. By replacing the
image() function's X and Y parameters with mouseX then mouseY,
respectively and one at a time, you can run the sketch with the
image of the wheel attached to either the mouse's X or Y position.
Place the wheel in the position it should be in, the println() function
(when uncommented) will print out the position of your mouse, note this
value and replace it with the mouseX or mouseY system variable in the
wheel's image() function's corresponding X or Y parameter.
As the imageMode() function is set to CENTER in this example you will
have to move the main cart image to a location that is not the origin,
so that the left and top halves of the image is not obscured by the
boundaries of the Display Window. You will then need to subtract the
value that you added to the X and Y parameters of the image() function
to draw the cart from the respective values printed in the Text
Area/debugging console that will be used to place the wheels in the
correct locations.
Now that we have a template from which to start let's set up a
temporary system that allows the cart to trail after the mouse with a
bit of friction, we'll then modify this code to suit the needs of our
sketch. This methodological approach to sketching by creating a rough
idea then refining it will allow us to see results much sooner in the
sketching process, rather than spending a lot of time on a sketch only
to find out when it is almost done that the effect we were trying to
achieve isn't quite working out.
We'll start by adding the following global variables:
float xPos;
float difX;
int drag = 30;
If you recall from the imageScroll.pde sketch, we used the technique of
creating the impression of friction with a similar set of global
variables. The only difference is that in this sketch we are now using
the same technique to create the impression of friction along the X
axis. Next we'll need to add the following statements to the draw()
structure after the imageMode() function call:
image(wheelBd, -75, 25);
image(cart, 0, 0);
image(wheelFd, -95, 35);
difX = mouseX - (xPos + cart.width/2);
xPos += difX/drag;
Since we want the cart to move with relation to the mouse moving past
the end of the cart on the right hand side, we're going to divide the
cart.width object variable by 2 and add it to the position of the cart
which is now determined by the center of the cart object because we
have set imageMode() to CENTER. If imageMode() had been at it's default
value of CORNER we would simply use cart.width to determine the right
edge of the cart image.
To temporarily link these statements to the rendering of the cart,
directly after the previous statements add the following code:
pushMatrix();
translate(xPos, 250);
image(wheelBd, -75, 25);
image(cart, 0, 0);
image(wheelFd, -95, 35);
popMatrix();
Notice that we just added three additional statements. The first new
statement is pushMatrix() this tells Processing to store the current
transformational data of the coordinate system in memory, we then use
the translate() function to to modify the coordinate system along the X
axis by the value of the variable xPos and the numerical constant of
250 for the Y parameter. The Y parameter is a numerical constant simply
because it will not change throughout the duration that the sketch is
running. Next we render the images without any changes to their
parameters as all of their positional data remains the same, the
transform will create the impression of movement for us. Then finally
we use the popMatrix() function to restore the transformational data
relating to the coordinate system when pushMatrix() was initially
called.
When using pushMatrix() it must always be coupled with popMatrix() or
Processing will complain about there being too many calls to
pushMatrix() and not enough to popMatrix().
|
|