# PVector rotate use for 3D

**URL:** <https://discourse.processing.org/t/pvector-rotate-use-for-3d/10958>\
**Category:** Gallery\
**Created:** [May 6, 2019, 4:28am UTC](https://discourse.processing.org/t/pvector-rotate-use-for-3d/10958 "2019-05-06T04:28:35Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kll](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kll/32/964_2.png) [@kll](https://discourse.processing.org/u/kll)\
**Post date:** [May 6, 2019, 4:28am UTC](https://discourse.processing.org/t/pvector-rotate-use-for-3d/10958/1 "2019-05-06T04:28:35Z")

</div>

in the ref find:  
[https://processing.org/reference/PVector\_rotate\_.html](https://processing.org/reference/PVector_rotate_.html)  
only work 2D,  
now to rotate a PVector in 3D it still can be used / hacked

try:

```auto
// file: sketch_3D_PVector_rotate
// using mouseWheel Plus PLus for rotation

PVector a, atx, aty, atz, at;
int along = 50;
float angbx=0, angby=0, angbz=0;
boolean axprint = true, axline = true;

void setup() {
  size(600, 600, P3D);
  a = new PVector(along, along, along);
  info_print(); // Tab ptz
  println("here add: key [x] [y] [z] rotation axis / key [r] reset AND turn MouseWheel");
}

void draw () {
  background(200, 200, 0);
  PTZ();
}

// _____________________________________________________
void draw_object() { // called by / from inside ptz
  axis();
  trans();
  show_vector();
} 

void rotatePVX(float angbx) {
  // ______________________________________________ step 1 rotate a ( by x )
  atx = new PVector(a.y, a.z); // create a 2D vector
  atx.rotate(angbx); // rotate 2D original angle + MWPP angle
  atx.set(a.x, atx.x, atx.y); // restore to 3D 
  atx.sub(a); // get the move vector only

  at.add(atx); // by x
}

void rotatePVY(float angby) {
  // ______________________________________________ step 2 rotate a ( by y )  
  aty = new PVector(a.x, a.z);
  aty.rotate(angby);
  aty.set(aty.x, a.y, aty.y);
  aty.sub(a);

  at.add(aty); // by y
}

void rotatePVZ(float angbz) {
  // ______________________________________________ step 3 rotate a ( by z )
  atz = new PVector(a.x, a.y);
  atz.rotate(angbz);
  atz.set(atz.x, atz.y, a.z);
  atz.sub(a);

  at.add(atz); // by z
}

void trans() {
  at = a.copy(); // copy from original
  rotatePVX(angbx);
  rotatePVY(angby);
  rotatePVZ(angbz);
}

void axis() {
  int max = 100;
  stroke(200, 0, 0);
  strokeWeight(1);
  line(0, 0, 0, max, 0, 0);
  strokeWeight(0.3);
  line(0, 0, 0, -max, 0, 0);
  fill(200, 0, 0);
  text("x", max, 0);
  stroke(0, 200, 0);
  strokeWeight(1);
  line(0, 0, 0, 0, max, 0);
  strokeWeight(0.3);
  line(0, 0, 0, 0, -max, 0);
  fill(0, 200, 0);
  text("y", 0, max);
  stroke(0, 0, 200);
  strokeWeight(1);
  line(0, 0, 0, 0, 0, max);
  strokeWeight(0.3);
  line(0, 0, 0, 0, 0, -max);
  fill(0, 0, 200);
  text("z", 0, 0, max);
  fill(100, 100, 0, 10); // transparent not work
  noStroke();
  //max = 20; // so make it small
  //rect(-max, -max, 2*max, 2*max); // xy plane
}

void show_vector() {
  fill(200, 0, 200);
  noStroke();
  push();
  translate(a.x, a.y, a.z);
  sphere(3);
  pop();
  stroke(200, 0, 200);
  strokeWeight(3);
  line(a.x, a.y, a.z, 0, 0, 0);

  if ( axline ) {
    //show axis components
    stroke(80);
    strokeWeight(0.5);
    line(a.x, a.y, a.z, a.x, 0, 0);
    line(a.x, a.y, a.z, 0, a.y, 0);
    line(a.x, a.y, a.z, 0, 0, a.z);
  }
  // show rotated vector
  fill(0, 200, 200);
  noStroke();
  push();
  translate(at.x, at.y, at.z);
  sphere(3);
  pop();
  stroke(0, 200, 200);
  strokeWeight(3);
  line(at.x, at.y, at.z, 0, 0, 0);

  if ( axline ) {
    //show axis components
    stroke(80);
    strokeWeight(0.5);
    line(at.x, at.y, at.z, at.x, 0, 0);
    line(at.x, at.y, at.z, 0, at.y, 0);
    line(at.x, at.y, at.z, 0, 0, at.z);

    // show the at_i components
    push();
    stroke(0, 200, 200);
    strokeWeight(0.5);
    translate(a.x, a.y, a.z);
    line(0, 0, 0, atx.x, atx.y, atx.z);
    translate(atx.x, atx.y, atx.z);
    line(0, 0, 0, aty.x, aty.y, aty.z);
    translate(aty.x, aty.y, aty.z);
    line(0, 0, 0, atz.x, atz.y, atz.z);
    pop();
  }
}

void main_keyPressed(float e) { // called from pts void mouseWheel(MouseEvent event) {
  float speed = 0.056;
  if ( keyPressed && key == 'x' ) { 
    angbx += e * speed;
    if ( abs(angbx) > TAU ) angbx = 0;
    println(" key x: angbx "+int(degrees(angbx)));
  }
  if ( keyPressed && key == 'y' ) { 
    angby += e * speed;
    if ( abs(angby) > TAU ) angby = 0;
    println(" key y: angby "+int(degrees(angby)));
  }
  if ( keyPressed && key == 'z' ) { 
    angbz += e * speed;
    if ( abs(angbz) > TAU ) angbz = 0;
    println(" key z: angbz "+int(degrees(angbz)));
  }
  if ( keyPressed && key == 'r' ) {
    angbx=angby=angbz=0;
    println("reset");
  }
  if ( axprint ) {
    println("a"+a);
    println("atx"+atx);
    println("aty"+aty);
    println("atz"+atz);
    println("at"+at);
  }
}

// tab ptz

int mode = 0;
float Zmag = 2;
int Zaxis=-100;                                                       
float Xmag, Ymag = 0;
float newXmag, newYmag = 0; 
int newZmag = 0;
float newxpos, newypos = 0; // for PAN
float xposd, yposd = 0; // for PAN

// _________________________________________________________________ ROTATE / TILDE and MOVE / PAN
void mousePressed() {
  if (mouseButton == LEFT) mode=1; // ORBIT
  else if (mouseButton == RIGHT) mode=2; // PAN
  // else if (mouseButton == CENTER) mode=3; // zoom mouse wheel
}

// _________________________________________________________________ mouse PT end
void mouseReleased() { 
  mode = 0;
}

// _________________________________________________________________ mouseWheel ZOOM
void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  //println(e);
  if ( !keyPressed ) {
    float newZmag = event.getCount()/3.0; 
    Zmag += newZmag;
    //println("mouse event: "+newZmag+" Zmag "+Zmag);
  }
  main_keyPressed(e); // from main
}

// _______________________________________________ OPERATION
void keyPressed() {
  if ( keyCode == UP ) Ymag -= 0.1 ;
  if ( keyCode == DOWN ) Ymag += 0.1 ; 
  if ( keyCode == RIGHT) Xmag -= 0.1 ; 
  if ( keyCode == LEFT ) Xmag += 0.1 ;
  if ( keyCode == 16 ) Zmag -= 0.2 ; // [Page Down]
  if ( keyCode == 11 ) Zmag += 0.2 ; // [Page Up]
  //println("key: "+key); println("keyCode: "+keyCode);
}

// _______________________________________________
void keyReleased() {
}

// ________________________________________________ Pan Tilde Zoom
void PTZ() {
  pushMatrix(); 
  translate(width/2, height/2, Zaxis);
  // get new mouse operation  
  if ( mode == 2 ) { // PAN ( right mouse button pressed)
    xposd = (mouseX-float(width/2));
    yposd = (mouseY-float(height/2));
  }  
  newxpos = xposd;// xposd=0;
  newypos = yposd;// yposd = 0; 
  translate(newxpos, newypos, 0); // move object
  if ( mode == 1 ) { // ORBIT ( left mouse button pressed)
    newXmag = mouseX/float(width) * TWO_PI;
    newYmag = mouseY/float(height) * TWO_PI;

    float diff = Xmag-newXmag;
    if (abs(diff) > 0.01) Xmag -= diff/4.0;
    diff = Ymag-newYmag;
    if (abs(diff) > 0.01) Ymag -= diff/4.0;
  }
  rotateX(-Ymag);   
  rotateY(-Xmag);   
  scale(Zmag);
  draw_object(); // THE OBJECT
  popMatrix();
}

// _______________________________________________ SETUP PRINT INFO
void info_print() {
  println("PTZ info:");
  println("key UP DOWN RIGHT LEFT -> rotate // key PAGE UP DOWN -> zoom");
  println("mouse LEFT press drag up down right left -> rotate");
  println("mouse RIGHT press -> move ");
  println("mouse WHEEL turn -> zoom");
}
// _______________________________________________

```

 ![SNAG-0105](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/721eca17bda081a39aea3a346b2ae850a26dab23.jpeg)

yes, the code is lengthy,  
but the rotation part not,

- only the axis / axis components / move vector / part
- MouseWheel Plus Plus operation ( x y z invisible slider )
- and the **Pan-tilt-zoom** (PTZ) operation/show makes it long.

* * *

same trick used here [Intersection between point and plane in 3D or more](https://discourse.processing.org/t/intersection-between-point-and-plane-in-3d-or-more/10780/7) already

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 6, 2019, 10:35am UTC](https://discourse.processing.org/t/pvector-rotate-use-for-3d/10958/2 "2019-05-06T10:35:21Z")

</div>

interesting

PTZ is for “Pan–tilt–zoom camera” ?

---

<div class="post-metadata">

**Author:** ![hamoid](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hamoid/32/58_2.png) [@hamoid](https://discourse.processing.org/u/hamoid)\
**Post date:** [May 6, 2019, 11:00am UTC](https://discourse.processing.org/t/pvector-rotate-use-for-3d/10958/3 "2019-05-06T11:00:44Z")

</div>

Nice that you figured out your own rotate function! 🙂 If you need such methods another option is to use `Vec3D` from toxiclibs (instead of PVector). It implements rotations and much more. [https://github.com/postspectacular/toxiclibs/blob/master/src.core/toxi/geom/Vec3D.java](https://github.com/postspectacular/toxiclibs/blob/master/src.core/toxi/geom/Vec3D.java)
