P2Matrix to turn around axis

Hi, I’m trying to turn a PVector to 60 degree with a PMatrix2D.
I found this formula : https://en.wikipedia.org/wiki/Rotation_matrix
But I don’t find the right way to code it. Results are always on the down of the screen.
Where’s my code :

PVector green, blue;
PMatrix2D matrix;
int angle = 60;
float rad;
void setup() {
  size(360, 360);
  smooth();
  rad = radians(angle);
  green = new PVector(0, 0);
  blue = new PVector(0, 0);
  matrix = new PMatrix2D(cos(rad), -sin(rad), sin(rad), cos(rad), 0, 1);
}
void draw() {
  background(144);
  scale(width, height);
  noStroke();
  fill(10, 205, 60);
  ellipse(green.x, green.y, 0.1, 0.1);
  fill(10, 60, 205);
  ellipse(blue.x, blue.y, 0.1, 0.1);
}
void keyPressed() {
  matrix.mult(green, blue);
}

Thanks

i haven’t run your code but it seems you don’t apply the matrix anywhere. you would need to push/pop a matrix transform. anyways i just wanted to point out there is a rotate method within the PVector class that can be used to rotate a vector while maintaining its magnitude.

1 Like

Hello,

Your matrix should be:

  matrix = new PMatrix2D(cos(rad), -sin(rad), 0, 
                         sin(rad), cos(rad), 1);

Modified your code and rotates in 60 deg increments if key pressed:

PVector green, blue;
PMatrix2D matrix;
int angle = 60;
float rad;

void setup() 
  {
  size(360, 360);
  smooth();
  rad = radians(angle);
  green = new PVector(200, 0); //source
  blue = new PVector(0, 0);    //target
  matrix = new PMatrix2D();
  //matrix.set(cos(rad), -sin(rad), 0, 
  //           sin(rad), cos(rad), 1);
  }

void draw() 
  {
  background(144);
  translate(width/2, height/2);
  noStroke();
  strokeWeight(3);
  fill(10, 205, 60);
  stroke(10, 205, 60);
  line(0, 0, green.x, green.y);
  noStroke();
  ellipse(green.x, green.y, 10, 10);
  fill(10, 60, 205);
  stroke(10, 60, 205);
  line(0, 0, blue.x, blue.y);
  noStroke();
  ellipse(blue.x, blue.y, 10, 10);
  }

void keyPressed()
  {
  matrix.set(cos(rad), -sin(rad), 0, 
             sin(rad), cos(rad), 1);
  matrix.mult(green, blue);
  rad += TAU/6;                  //TAU/6 rad = TWO_PI/6 rad = 60 deg
  }

:slight_smile:

1 Like

Ok, acutally we are close to the solution but I need to use scale(width, height);
This code is a pre-test to use with a texture on a triangle where value are normalized.
I try this without sucess :

PVector green, blue;
PMatrix2D matrix;
int angle = -30;
float rad;
void setup(){
  size(360, 360);
  smooth();
  rad = radians(angle);
  green = new PVector(0.5, 0.5); //source
  blue = new PVector(0.8, 0.5);    //target
  matrix = new PMatrix2D();
}
void draw() {
  background(144);
  scale(width, height);
  noStroke();
  fill(10, 205, 60);
  ellipse(green.x, green.y, 0.10, 0.10);
  fill(10, 60, 205);
  noStroke();
  ellipse(blue.x, blue.y, 0.10, 0.10);
}
void keyPressed() {
  matrix.set(cos(rad), -sin(rad), 0.5*(1-cos(rad))+0.5*(sin(rad)), 
    sin(rad), cos(rad), 0.5*(1-cos(rad))-0.5*(sin(rad)));//to turn around center
  matrix.mult(green, blue);
  rad -= TAU/6;                  //TAU/6 rad = TWO_PI/6 rad = 60 deg
}

I think I’m lost the way to write arguments in matrix.set( …).
How to write to turn around 0.5 point ?

Hi @matheplica,

PMatrix2D is a 3 x 2 matrix in row-major order. The first column describes the right axis; the second, the up axis; the third column describes the translation. Transform matrices are usually described as square matrices, but the last row – 0.0, 0.0, 1.0 – is left out.

| m00: right axis x | m01: up axis x | m02: translation x |
| m10: right axis y | m11: up axis y | m12: translation y |
| 0.0 | 0.0 | 1.0 |

To combine a translation, rotation and scale matrices, you can use matrix multiplication. Matrix multiplication is not commutative, so there are two instance methods: apply and preApply. The matrix that calls apply is the left operand; preApply, the right.

PMatrix2D t = new PMatrix2D();
PMatrix2D r = new PMatrix2D();
PMatrix2D s = new PMatrix2D();

t.translate(10.0, 20.0);
t.print();

r.rotate(radians(30.0));
r.print();

s.scale(40.0, 50.0);
s.print();

PMatrix2D m = new PMatrix2D();
m.apply(t);
m.apply(r);
m.apply(s);
m.print();

Just an opinion, but I imagine it’d be less confusing if you used only matrix operations – or only the renderer’s translate, rotate and scale – but not both.

As far as UV coordinates, are you looking to do something like this?

0024
Animated Gif

// Define triangle shape.
PVector a = new PVector(1.0, 0.0, 0.0);
PVector b = new PVector(-0.5, -0.86602545, 0.0);
PVector c = new PVector(-0.5, 0.86602545, 0.0);

// Define triangle uvs relative to real world coordinates.
PVector uvcenter = new PVector(0.5, 0.5);
PVector s = PVector.add(PVector.mult(a, 0.5), uvcenter);
PVector t = PVector.add(PVector.mult(b, 0.5), uvcenter);
PVector u = PVector.add(PVector.mult(c, 0.5), uvcenter);

// Create vectors to store uvs transformed by matrix.
PVector sp = new PVector();
PVector tp = new PVector();
PVector up = new PVector();

// A texture to use on the shape.
PImage txtr;

// Matrices to store the real world and uv transform.
PMatrix2D shapetr = new PMatrix2D();
PMatrix2D uvtr = new PMatrix2D();

void setup() {
  size(256, 256, P2D);
  noStroke();
  
  // Set uv coordinate range to [0.0, 1.0].
  // Specify that the texture will repeat when uv
  // coordinates exceed that range.
  textureWrap(REPEAT);
  textureMode(NORMAL);
  
  // To make the rotation easier to see, a very
  // small image is sampled with no smoothing.
  ((PGraphicsOpenGL)getGraphics()).textureSampling(2);
  txtr = rgb(16, 16);

  // Transform the shape.
  shapetr.translate(width * 0.5, height * 0.5);
  shapetr.rotate(radians(0.0));
  shapetr.scale(width * 0.485, height * 0.485);

  a = shapetr.mult(a, new PVector());
  b = shapetr.mult(b, new PVector());
  c = shapetr.mult(c, new PVector());
}

void draw() {

  // Animate the uv transform.
  uvtr.reset();
  uvtr.translate(0.5, 0.5);
  uvtr.rotate(frameCount * 0.03);
  uvtr.translate(-0.5, -0.5);

  // Apply the transform to the uv coords.
  uvtr.mult(s, sp);
  uvtr.mult(t, tp);
  uvtr.mult(u, up);

  // Display the shape.
  background(#fff7d5);
  beginShape(POLYGON);
  texture(txtr);
  vertex(a.x, a.y, sp.x, sp.y);
  vertex(b.x, b.y, tp.x, tp.y);
  vertex(c.x, c.y, up.x, up.y);
  endShape(CLOSE);
}

// Create a test image.
PImage rgb(int w, int h) {
  PImage result = createImage(w, h, ARGB);
  result.loadPixels();
  for (int i = 0, y = h - 1; y > -1; --y) {
    float gr = y * 255.0 / (h - 1);
    for (int x = 0; x < w; ++x, ++i) {
      float re = x * 255.0 / (w - 1);

      result.pixels[i] = color(
        re, gr, 127.0, 255.0);
    }
  }
  result.updatePixels();
  return result;
}

You can translate a matrix by the pivot, (0.5, 0.5), rotate, then shift back by translating with the negative pivot.

Hope that moves the ball forward,
Jeremy

2 Likes

Ok Jeremy, thanks.
I can continue now,
hope to share one day my works but the road is long

1 Like