cmxu
cmxu

Reputation: 972

3D-Rotation of a Rectangular Prism

I was messing around with processing creating some 3D objects, and I created a recursive method that I hope to generate a finger-like object with more degrees of freedom. The idea is that each segment, displayed as a box, generates a new segment so that it's bottom face is at the same location as the previous segment's bottom (shown below).Segment Finger

The problem is that when I try to rotate more than one axis (i.e. set both deltaX and deltaZ to be 0.3) my algorithm fails and I get something weird (show below). Broken Segment Finger

I used rotation matrices in order to try to calculate where the base of the new segment should be based on the old one and it works for only 1 rotating axis but fails on multiple (the math is in the if statement). I've seen posts about Quaternions, but I'm really just curious why my matrix math doesn't work, or if Quaternions are really so much better how I might implement them in my code. Thanks in advance!

void finger(float x, float y, float z, float rx, float ry, float rz, float r, 
float h){
  translate(x,-y,z);
  rotateX(rx);
  rotateY(ry);
  rotateZ(rz);
  translate(0,-h/2,0);
  box(r,h,r);
  translate(0,h/2,0);
  rotateZ(-rz);
  rotateY(-ry);
  rotateX(-rx);
  translate(-x,y,-z);
  if(r>10){
    finger(x+h*sin(rx)*sin(ry)*cos(rz)+h*cos(rx)*sin(rz),y-h*sin(rx)*sin(ry)*sin(rz)+  
    h*cos(rx)*cos(rz),z-h*sin(rx)*cos(ry),rx+deltaX,ry+deltaY,rz+deltaZ,r-4,h-5);
  }
}

[Edit: MCVE Below, includes my code for moving around in 3D space, and setup/variable initialization] [Edit(2):MCVE Updated, change deltaX,deltaY,deltaZ for movement]

float deltaX,deltaY,deltaZ;
void setup(){
  deltaX=0;
  deltaY=0;
  deltaZ=0;
  fullScreen(P3D);
}
void draw(){
  noStroke();
  camera(-600, -400, -600, 0, -300, 0, 0, 1, 0);
  background(#51B6F5);
  directionalLight(255,255,255,0.5,1,0.5);
  directionalLight(255,255,255,-0.5,1,-0.5);
  box(400,10,400);
  tree(0,0,0,0,0,0,40,100);
}
void tree(float x, float y, float z, float rx, float ry, float rz, float r, float h){
  translate(x,-y,z);
  rotateX(rx);
  rotateY(ry);
  rotateZ(rz);
  translate(0,-h/2,0);
  box(r,h,r);
  translate(0,h/2,0);
  rotateZ(-rz);
  rotateY(-ry);
  rotateX(-rx);
  translate(-x,y,-z);
  if(r>10){
    tree(x+h*sin(rx)*sin(ry)*cos(rz)+h*cos(rx)*sin(rz),y-h*sin(rx)*sin(ry)*sin(rz)+h*cos(rx)*cos(rz),z-h*sin(rx)*cos(ry),rx+deltaX,ry+deltaY,rz+deltaZ,r-4,h-5);
  }
}

Upvotes: 1

Views: 779

Answers (1)

Kevin Workman
Kevin Workman

Reputation: 42176

I'm not exactly sure what the rotations and translations you have after you draw each box are doing. They were causing your transformations not to really "stack". I could stare at them for another hour to come up with why they resulted in that behavior, but I'm not great at 3D stuff.

But think about it this way:

At the end of each call to tree(), you want your origin to be at the top of the box you just drew (the bottom of the box you're about to draw), and you want the rotations to "stack".

If you approach it that way, then you only need to do a few things- first you'll do your rotation (since the origin is already at the bottom), then you'll translate to the center to draw your box, then you'll translate to the top of your box, which is where you want the bottom of the next box to be. Probably easier just to show you the code:

void tree2(float x, float y, float z, float rx, float ry, float rz, float r, float h){

  //assume current origin is at bottom of box

  //rotate around bottom
  rotateX(rx);
  rotateY(ry);
  rotateZ(rz);

  //move to center
  translate(0,-h/2,0);

  //draw the box
  box(r,h,r);

  //move origin to the top of the box- the bottom of the next box
  translate(0,-h/2,0);

  //draw the next box
  if(r>10){
    tree2(x+h*sin(rx)*sin(ry)*cos(rz)+h*cos(rx)*sin(rz),y-h*sin(rx)*sin(ry)*sin(rz)+h*cos(rx)*cos(rz),z-h*sin(rx)*cos(ry),rx+deltaX,ry+deltaY,rz+deltaZ,r-4,h-5);
  }
}

That code seems to do what you want- it acts more like a "snake" with each section starting where the previous section ended.

By the way this is a fun little toy, I'd be curious to see what you end up doing with it!

Upvotes: 2

Related Questions