# PVector rotate use for 3D

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

try:

``````// 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

}

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);

}

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);

}

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");
}
//_______________________________________________

``````

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 already

interesting

PTZ is for â€śPanâ€“tiltâ€“zoom cameraâ€ť ?

1 Like

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

3 Likes