Wie ihr ja schon wisst nutzt Processing das kartesische Koordinatensystem. Wichtig ist darauf zu achten, dass bei Processing der Nullpunkt in der linken oberen Ecke liegt. Die X-Achse verläuft von links nach rechts und die Y-Achse von oben nach unten. Dies mag seltsam erscheinen ergibt sich aber aus der Tradition, dass Bitmaps halt immer so ausgelesen wurden.
In der Computergrafik wird fast immer mit dem kartesischen Koordinatensystem gearbeitet. Dies bietet einige Annehmlichkeiten, so kann man Koordinatensysteme auch verschieben, skalieren oder gar drehen. Das kann ich vielen Fällen das Zeichnen von Objekten vereinfachen. Stellt euch eine Animation eines Autos vor. Die Räder sollen beim fahren natürlich drehen. Wenn ihr dies per Processing zeichnet müsst ihr immer die aktuelle Position der Karosserie zu den Rädern addieren und diese dann drehen. Wenn ihr dies mit der Veränderung des Koordinatensystems macht ist dies um ein vielfaches Einfacher. Hier müsst ihr nur das Koordinatensystem verschieben, die Karosserie zeichnen und dann nochmals das Koordinatensystem verschieben für die jeweiligen Räder. Solche Koordinatensystem Änderungen nennt man Transformationen. Davon gibt es drei Grundarten:
- Translation – Verschiebung
- Rotation – Drehung
- Skalierung – Grössenveränderung
Zu beachten ist, dass solche Transformationen nicht kommutativ sind. Es kommt daher darauf an in welcher Reihenfolge ihr die Transformationen aufruft.
In Processing heissen die Befehle wie folgtdeutsche Version
Processing uses a Cartesian coordinate system. It is important to note that the zero point is in the upper left corner in processing. The X axis is from left to right and the Y axis is from top to bottom. While this might seem odd, it comes from the tradition that bitmaps were always read in that order. In computer graphics the cartesian coordinate system is almost always used.
In processing we can simplify the drawing of objects in many cases by assigning them their own local coordinate system. Imagine an animation of a car moving across the screen. If you draw this in processing you could add a value to the the x and y coordinates for every detail of the car to move it across the screen. When it comes to the wheels, it would get complicated as we would not only change the position relative to the car, but rotate every detail in relation to the wheel axis! But if we modify the coordinate systems this becomes a lot simpler. Such coordinate system changes are called transformations. There are three basic types:
- Translation – shifting
- Rotation
- Scaling
It should be noted that such transformations are not commutative. That means the order that you make the transformations will effect the output. In processing, the commands look like this:
translate(float x, float y) rotate(float angle) scale(float xScale, float yScale)
Wenn ihr im 3D Modus arbeitet gibt es natürlich noch die 3.Komponente.
Häufig wird in diesem Zusammenhang auch von lokalen und globalen Koordinatensystemen gesprochen. Das globale Koordinatensystem ist das Ursprungskoordinatensystem, in Processing wäre dies die obere linke Ecke. Wird das Koordinatensystem mit Transformiert so spricht man von einem lokalen Koordinatensystem(in Referenz zu dem globalen). Um zwischen diesen Koordinatensystemen zu wechseln gibt es von Processing aus zwei Befehle:
- pushMatrix() – sichert das aktuelle Koordinatensystem
- popMatrix() – setzt das Koordinatensystem auf die letzte gesicherte Postition
Diese beiden Befehle arbeiten nach dem Stack-Prinzip. Dies ist eine fast schon antike Form von Computer-Speicher-Methoden. Stellt euch einfach einen Stapel vor, wenn ihr pushMatrix aufruft, wird der Stapel um eine Blatt erhöht. Auf diesem Blatt wären in unserem Bespiel die aktuellen Daten unseres Koordinatensystem beschrieben. Nun kann man rotieren, scalieren und transformieren wie man will. Wenn man jetzt jedoch das Koordinatensystem wieder an die Position von vor dem letzten pushMatrix-Aufruf bringen will, dann muss man popMatrix aufrufen. Nun wird dies Blatt vom Stapel entfernt.
Mit einem Beispiel-Programm sollte dies besser zu Verstehen seinIf you work in 3D mode, there is a third parameter for the z axis.
Frequently, local and global coordinate systems will be used. The global coordinate system is the original coordinate system, in processing this is the one fixed to the upper left corner. If the original coordinate system is transformed, then the result is local coordinate system (in reference to the global). To switch between these coordinate systems, there are two commands from Processing:
- pushMatrix() – save the current coordinate system
- popMatrix() – return to the last saved coordinate system
These two commands work according to the stack principle. This is an very old form of working with computer memory. Just imagine a stack of graph paper: when you call pushMatrix, the stack is increased by one sheet. On this page we would describe the current data of our coordinate system. Now you can rotate, scale and transform as you want. If you now want to bring the coordinate system back to the position of the last pushMatrix call, you must call popMatrix.
With an example program, this should be easer to understand:
Code Block |
---|
void setup() { size(400,400); // def. fenstergroessewindow size smoothstrokeWeight(15); // aktiviereline antialiasingthickness strokeWeight(15); // linienbreite } void draw() { background(255); // def. hintergrundfarbebackground colour float radius = dist(mouseX,mouseY,width/2,height/2); // rechne die distanz vom mousecursor zum fensterzentrum auscalculate the distance from the mouse curser to the center of the screen radius = map(radius,0,width,1,4); // rechnemodify austhe inradius welchemto bereichkeep derit radiuswithin ama schlussspecific seinrange. sollte pushMatrix(); translate(200,200); rotate(calcAngle()); scale(radius); smiley(); // funtionsfunction aufrufcall popMatrix(); pushMatrix(); translate(30,30); scale(.2); smiley(); // funtionsfunction aufrufcall popMatrix(); } // funktion void smiley() { noFill(); ellipse(0,0,180,180); // kopfhead fill(0); ellipse(0 - 30,0 - 30,20,20); // linkesleft augeneye ellipse(0 + 30,0 - 30,20,20); // rechtesright augeneye noFill(); arc(0,0,100,100,radians(20),radians(180-20)); // mundmouth } // berechne den winkel zur fenstermitter vom mausecursor auscalculate the angle from the screen middle to the mouse cursor // diethe winkelangle sindis in radiantradians float calcAngle() { return -atan2(mouseX - (width / 2),mouseY - (height / 2)); } |
Hier gibts gleich mehrere Neuigkeiten, Linie This example introduces a couple of new things starting on line 13:
float radius = dist(mouseX,mouseY,width/2,height/2);
Hier wird die Distanz vom Mauszeiger zur Fenstermitte ermittelt(Siehe Here the distance from the mouse pointer to the window centre is determined (see Pythagoras).
Linie 14:
radius = map(radius,0,width,1,4);
Hier eine Zahl auf einen anderen Zahlenbereich gemapt. Der Original-Bereich ist von 0-width. Der Ziel-Bereich ist von The original range is from 0 to the width of the window. The target range is from 1-4. Nun wird radius von Original-Bereich auf den Ziel-Bereich transformiert.
Aufgaben
Schreib ein Programm welches einen Smiley am Mauszeiger folgen lässt. Dazu soll ein kleineres Smiley um den grossen Smiley in einer Umlaufbahn kreisen.Now radius is transformed from original range to the target range.
-atan2(mouseX - (width / 2),mouseY - (height / 2));
The atan2 function returns the angle in radians at a given coordinate from the 0 point. In this example we shift the 0 point to the centre of the screen by subtracting width/2 from X and height/2 from Y.
Image Credit: wikipedia
Exercise 8
Create a new program where a simple car follows the mouse on the screen from left to right. The car should be drawn from the side, and include wheels that rotate. You may use the example code to get started.
Code Block | ||
---|---|---|
| ||
int rotation;
void setup()
{
size(900, 400); // def. window size
}
void draw()
{
rotation++;
}
void car(int x, int y) {
fill(100);
beginShape();
vertex(0, 0);
vertex(5, -50);
vertex(50, -50);
vertex(70, -80);
vertex(150, -80);
vertex(190, -50);
vertex(265, -45);
vertex(270, 0);
vertex(0, 0);
endShape();
wheel(60, 0);
wheel(210, 0);
}
void wheel(int x, int y) {
int radius = 25;
fill(150);
stroke(0);
strokeWeight(7);
ellipse(0, 0, radius*2, radius*2);
strokeWeight(4);
line(0-radius, 0, 0+radius, 0);
line (0, 0-radius, 0, 0+radius);
noStroke();
}
|
Possible Solution:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
int rotation;
boolean forward = true;
int xScale = 1;
void setup()
{
size(900, 400);
}
void draw()
{
background(255);
int mouseMovement = mouseX-pmouseX; //pmousex gives us our mouse x value from the last frame. Subtracting from the current position give us the distance moved per frame
if (mouseMovement<0) { // if the movement is negative, then we flip everthing backwards with a negative xcale
xScale = -1;
}
if (mouseMovement>0) { // if the movement is positive, then our xscale is positive
xScale = 1;
}
rotation+= abs(mouseMovement);
car(mouseX, height/2);
}
void car(int x, int y) {
pushMatrix();
translate(x, y);
scale(xScale, 1);
fill(100);
beginShape();
vertex(0, 0);
vertex(5, -50);
vertex(50, -50);
vertex(70, -80);
vertex(150, -80);
vertex(190, -50);
vertex(265, -45);
vertex(270, 0);
vertex(0, 0);
endShape();
wheel(60, 0);
wheel(210, 0);
popMatrix();
}
void wheel(int x, int y) {
int radius = 25;
fill(150);
stroke(0);
pushMatrix();
translate(x, y);
rotate(radians(rotation));
strokeWeight(7);
ellipse(0, 0, radius*2, radius*2);
strokeWeight(4);
line(0-radius, 0, 0+radius, 0);
line (0, 0-radius, 0, 0+radius);
noStroke();
popMatrix();
}
|