Shear box left and right AND up and down?

Hello everyone!

I am trying to skew a box left and right and up and down. If the box is rotated appropriately (I am actually using a .obj file for the box, because I’ll want to use other .obj files after this test), I can use shearX to skew it left and right. However, I have not figured out a way to shear it up and down using shearY or another method.

(I do not believe that rotating the objects or manipulating a camera will do for this particular application.)

Does anyone have a suggestion?


// "a" and "s" work to skew left to right
// "z" and "x" obviously do not work to skew up and down

float rot_X = 1.4;
float rot_Y =0;
float rot_Z = 0;
float shearX = 0;
float shearY = 0;

void setup() {
  size(640, 360, P3D);
}

void draw() {  
  background(255);

  translate(width/2 + rot_X, height/2, 0);
  rotateX(rot_X);
  rotateZ(rot_Z);   
  rotateY(rot_Y);    
  shearX(shearX);
  shearY(shearY);
  noFill();
  box(100);
}

void keyPressed() {
  if (key == 'a') {
    shearX += .1;
  }
  if (key == 's') {
    shearX -= .1;
  }    
  if (key == 'z') {
    shearY += .1;
  }
  if (key == 'x') {
    shearY -= .1;
  }    
  println("shearX/shearY: " + shearX + ", " + shearY);
}

shear

Looking at the code there’s only shearX/Y and perhaps designed for 2D transformation

so maybe it’s good to define your 3D version of shearX/Y/Z.
(I just guessed it and cannot guarantee that it’s right)

// "a" and "s" work to skew left to right
// "z" and "x" obviously do not work to skew up and down

float rot_X = 1.4;
float rot_Y =0;
float rot_Z = 0;
float shearX = 0;
float shearY = 0;

void setup() {
  size(640, 360, P3D);
}

void shearY3D(float angle) {
  float t = (float) Math.tan(angle);
  applyMatrix(1, 0, 0, 0, 
    0, 1, 0, 0, 
    0, t, 1, 0, 
    0, 0, 0, 1);
}

void draw() {  
  background(255);

  translate(width/2 + rot_X, height/2, 0);
  rotateX(rot_X);
  rotateZ(rot_Z);   
  rotateY(rot_Y);    
  shearX(shearX);
  shearY3D(shearY);
  noFill();
  box(100);
}

void keyPressed() {
  if (key == 'a') {
    shearX += .1;
  }
  if (key == 's') {
    shearX -= .1;
  }    
  if (key == 'z') {
    shearY += .1;
  }
  if (key == 'x') {
    shearY -= .1;
  }    
  println("shearX/shearY: " + shearX + ", " + shearY);
}

note that shearing won’t happen as you drew because the shape is already offset to width/2, height/2. So you need to play around with the order of transformation… or simply define a mesh with vertices each frame so you can directly manipulate the coordinate (if your obj mesh doesn’t have too many polygons)

ok I just noticed that my reply was totally rubbish as I missed that you have rotations in it, which basically changed the axes - you thought you are applying shearY but it was applied to the Z axis because matrix transformation is applied in the order you execute.

so this shows proper shearing

// "a" and "s" work to skew left to right
// "z" and "x" obviously do not work to skew up and down

float rot_X = 1.4;
float rot_Y =0;
float rot_Z = 0;
float shearX = 0;
float shearY = 0;

void setup() {
  size(640, 360, P3D);
}

//void shearY3D(float angle) {
//  float t = (float) Math.tan(angle);
//  applyMatrix(1, 0, 0, 0, 
//    t, 1, 0, 0, 
//    0, 0, 1, 0, 
//    0, 0, 0, 1);
//}

void draw() {  
  background(255);

  //translate(width/2 + rot_X, height/2, 0);
  //rotateX(rot_X);
  //rotateZ(rot_Z);   
  //rotateY(rot_Y);    
  translate(width/2, height/2, 0);
  shearX(shearX);
  shearY(shearY);
  noFill();
  box(100);
}

void keyPressed() {
  if (key == 'a') {
    shearX += .1;
  }
  if (key == 's') {
    shearX -= .1;
  }    
  if (key == 'z') {
    shearY += .1;
  }
  if (key == 'x') {
    shearY -= .1;
  }    
  println("shearX/shearY: " + shearX + ", " + shearY);
}

and perhaps the effect you want is actually not shearing. I don’t exactly know how this is called, but camera frustum may be something you can hack to achieve what you want

https://processing.org/reference/frustum_.html

Hi @jetjaguar

Have a look into the methods rotateX(), rotateY() and rotateZ(). I believe they are what you are looking for
https://processing.org/reference/rotateX_.html
https://processing.org/reference/rotateY_.html
https://processing.org/reference/rotateZ_.html

simple example:

/**
 * Load and Display an OBJ Shape. 
 * 
 * The loadShape() command is used to read simple SVG (Scalable Vector Graphics)
 * files and OBJ (Object) files into a Processing sketch. 
 */


PShape rocket;

float rx, ry, rz;
  
public void setup() {
  size(640, 360, P3D);
    
  rocket = loadShape("rocket.obj");
}

public void draw() {
  background(0);
  lights();
  
  translate(width/2, height/2 + 100, -200);
  rotateZ(PI);
  rotateY(ry);
  rotateX(rx);
  rotateZ(rz);
  shape(rocket);
  
  ry += 0.03;
  rx += 0.005;
  rz += 0.01;
}

best regards

Thank you both for your replies!

I’m looking at frustum for the first time, and I suppose that’s related to what I’m trying to achieve. I think that the best way to understand what I’m trying to do is to run my original code, then press the s key and the a key to see how the box skews left and right. That works perfectly. Now I also want to achieve the same effect going up and down, so it would be as if you are grabbing the face of the box that is closest to you and pulling it up. The graphic I added to the post illustrates this.

Note that the simple box is just a stand in for more complex .obj that I’ll use later (I was surprised to see that shear() works with .obj’s, but it does in the same manner that box() does.)

Well, it seems as though I can create the same effect when I’m using an obj. file by setting it up so that the origin point, or point of rotation, is at the backside of the object, and not in the middle of it. Then just use the rotation() functions as normal.