Find centre of pyramid and rotate from there, not the apex

Hi all,
How can I rotate this from a centre point within the geometry rather from the vertex /apex (not sure of the correct terminology)

PGraphics canvas;
PVector[] basePts = new PVector[3];

void setup() {
  size(768, 768, P3D);  
  canvas = createGraphics(width, height, P3D);
}

void draw() {
 
  canvas.beginDraw();
  canvas.background(0);
  canvas.noStroke();

  canvas.pushMatrix();
  
  canvas.translate(width/2, height/2, 0);
  canvas.rotateZ(PI/2);
  
  canvas.rotateY(radians(frameCount/2 % 360));
  
  for (int i = 0; i < 3; ++i ) {
  float ang = TWO_PI * i / 3;
   basePts[i] = new PVector(cos(ang) * 400/2, sin(ang) * 400/2, -400/2);
  }
 
  canvas.fill(255);
  canvas.strokeWeight(3);
  canvas.stroke(123);
  
  canvas.beginShape(TRIANGLES);
  for (int i = 0; i < 3; ++i ) {
    int i2 = (i+1) % 3;
  canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  canvas.vertex(basePts[i2].x, basePts[i2].y, basePts[i2].z);
  canvas.vertex(0, 0, PI/2);
}
  canvas.endShape();//sides
  
  beginShape(); //base
  for (int i = 0; i < 3; ++i ) {
    canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  }
  endShape(CLOSE);
  
  canvas.popMatrix();
  canvas.endDraw();

  blendMode(BLEND);
  image(canvas, 0, 0);
}

Many thanks for any suggestions.

Hello @JonnieNightTime

In this section:

I changed this:

canvas.vertex(0, 0, PI/2);

To this:

canvas.vertex(0, 0, 180);

It moved the rotation off the apex.
It’s not prefect, in that now there is a bit of perspective distortion which needs to be cleaned up.
But it’s a place to start. :slightly_smiling_face:

:nerd_face:

1 Like

here is my version with mouse rotation


PGraphics canvas;
PVector[] basePts = new PVector[3];

float angleMouseX, angleMouseY; 

void setup() {
  size(768, 768, P3D);  
  canvas = createGraphics(width, height, P3D);

  for (int i = 0; i < 3; i++ ) {
    float ang = TWO_PI * i / 3;
    basePts[i] = new PVector(cos(ang) * 400/2, 
      sin(ang) * 400/2, 
      -100  );
    println(basePts[i]);
  }
}

void draw() {
  angleMouseX = map(mouseX, 0, width, -TWO_PI, TWO_PI);
  angleMouseY = map(mouseY, 0, height, height+200, -200);

  float rad = 810; 
  float posX = (0) + cos(angleMouseX) * rad ;
  float posZ = 0 + sin(angleMouseX) * rad ;
  canvas.camera(posX, angleMouseY, posZ, 
    width/2.0-0, height/2.0, 0, 
    0, 1, 0);

  //  canvas.camera(); 

  canvas.beginDraw();
  canvas.background(0);
  canvas.lights(); 
  canvas.noStroke();

  canvas.pushMatrix();
  canvas.translate(width/2, height/2, 0);
  //  canvas.rotateZ(PI/2);
  //  canvas.rotateY(radians(frameCount/2 % 360));

  canvas.fill(255);
  canvas.strokeWeight(3);
  canvas.stroke(123);

  //sides
  canvas.beginShape(TRIANGLES);
  for (int i = 0; i < 3; i++ ) {
    int i2 = (i+1) % 3;
    canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
    canvas.vertex(basePts[i2].x, basePts[i2].y, basePts[i2].z);
    canvas.vertex(0, 0, 100);
  }
  canvas.endShape();//sides

  //base
  canvas.fill(255, 0, 9); 
  canvas.beginShape(); //base
  for (int i = 0; i < 3; i++ ) {
    canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  }
  canvas.endShape(CLOSE);

  canvas.popMatrix();
  canvas.endDraw();

  blendMode(BLEND);
  image(canvas, 0, 0);
}

2 Likes

here is an other version

the base is in the X Z plane (like standing on a table), the top is in y direction

This reflects more my approach for P3D that the room / space has its floor in X Z plane (like standing on a table)


PGraphics canvas;
PVector[] basePts = new PVector[3];

float angleMouseX, angleMouseY; 

void setup() {
  size(768, 768, P3D);  
  canvas = createGraphics(width, height, P3D);

  for (int i = 0; i < 3; i++ ) {
    float ang = TWO_PI * i / 3;
    basePts[i] = new PVector(cos(ang) * 400/2, 
      -100, 
      sin(ang) * 400/2  );
    println(basePts[i]);
  }
}

void draw() {

  background(0);
  lights(); 
  //noStroke();

  //angleMouseX = map(mouseX, 0, width, -TWO_PI, TWO_PI);
  //angleMouseY = map(mouseY, 0, height, height+200, -200);

  //float rad = 810; 
  //float posX = (0) + cos(angleMouseX) * rad ;
  //float posZ = 0 + sin(angleMouseX) * rad ;
  //camera(posX, angleMouseY, posZ, 
  //  width/2.0-0, height/2.0, 0, 
  //  0, 1, 0);

  // camera(); 

  translate(width/2, height/2, 0);
  rotateX(radians(frameCount/8 % 360));
  rotateY(radians(frameCount/2 % 360));

  fill(255);
  strokeWeight(3);
  stroke(123);

  //sides
  beginShape(TRIANGLES);
  for (int i = 0; i < 3; i++ ) {
    int i2 = (i+1) % 3;
    vertex(basePts[i].x, basePts[i].y, basePts[i].z);
    vertex(basePts[i2].x, basePts[i2].y, basePts[i2].z);
    vertex(0, 100, 0 );
  }
  endShape();//sides

  //base
  fill(255, 0, 9); 
  beginShape(); //base
  for (int i = 0; i < 3; i++ ) {
    vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  }
  endShape(CLOSE);
}

2 Likes

nice - thanks both. Here’s where I’m taking it - inspired by classic cognitive psychology - Kanisza’s triangle Kanizsa triangle - New World Encyclopedia

PGraphics canvas;
PVector[] basePts = new PVector[3];
PVector[] basePtsBlk = new PVector[3];
float angleMouseX, angleMouseY;

void setup() {
  size(768, 768, P3D);  
  canvas = createGraphics(width, height, P3D);
  
    for (int i = 0; i < 3; i++ ) {
    float ang = TWO_PI * i / 3;
    basePts[i] = new PVector(cos(ang) * 400/2, -100, sin(ang) * 400/2 );
    println(basePts[i]);
  }
}

void draw() {
 
  canvas.beginDraw();
  canvas.background(30);
  canvas.camera(mouseX, height/2, (height/2) / tan(PI/6), width/2, height/2, 0, 0, 1, 0);
  canvas.noStroke();
  //canvas.ambientLight(255, 0, 0);
  //canvas.directionalLight(0, 255, 0, 0, -1, 0);
  //canvas.spotLight(0, 0, 255, width/2, height/2, 100, 0, 0, -1, PI/4, 2);
  canvas.ortho(-width/2, width/2, -height/2, height/2);
  
/// white pyramid
  canvas.pushMatrix();
  canvas.translate(width/2, height/2, 0);
  canvas.rotateX(radians(frameCount*0.99 % 360));
  canvas.rotateZ(radians(frameCount/2 % 360));
  
  canvas.fill(255);
  canvas.strokeWeight(1);
  canvas.stroke(0);
  
  //sides
  canvas.beginShape(TRIANGLES);
  for (int i = 0; i < 3; ++i ) {
    int i2 = (i+1) % 3;
  canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  canvas.vertex(basePts[i2].x, basePts[i2].y, basePts[i2].z);
  canvas.vertex(0, 180, 0 );
}
  canvas.endShape();//sides
  
  canvas.beginShape(); //base
  canvas.fill(255); 
  for (int i = 0; i < 3; ++i ) {
    canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  }
  canvas.endShape(CLOSE);
  canvas.popMatrix(); /// white pyramid end
  
  /// pyramid 2 (blk)
  canvas.pushMatrix();
  canvas.translate(width/2+5, height/2-3, 0);
  canvas.rotateY(radians(frameCount % 360)*-1);
  canvas.rotateZ(radians(frameCount/1.8 % 360*-1));
  
  canvas.fill(0);
  canvas.strokeWeight(2);
  canvas.stroke(50);
  
  //sides
  canvas.beginShape(TRIANGLES);
  for (int i = 0; i < 3; ++i ) {
    int i2 = (i+1) % 3;
  canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  canvas.vertex(basePts[i2].x, basePts[i2].y, basePts[i2].z);
  canvas.vertex(0, 180, 0 );
}
  canvas.endShape();//sides
  
  canvas.beginShape(); //base
  canvas.fill(0); 
  for (int i = 0; i < 3; ++i ) {
    canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  }
  canvas.endShape(CLOSE);
  canvas.popMatrix(); ///  pyramid 2 (blk) end
  
    /// pyramid 3 (blk)
  canvas.pushMatrix();
  canvas.translate(width/2-5, height/2+3, 0);
  canvas.rotateX(radians(frameCount*0.98 % 360)*-1);
  canvas.rotateZ(radians(frameCount/1.9 % 360));
  
  canvas.fill(0);
  canvas.strokeWeight(2);
  canvas.stroke(50);
  
  //sides
  canvas.beginShape(TRIANGLES);
  for (int i = 0; i < 3; ++i ) {
    int i2 = (i+1) % 3;
  canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  canvas.vertex(basePts[i2].x, basePts[i2].y, basePts[i2].z);
  canvas.vertex(0, 180, 0 );
}
  canvas.endShape();
  
  canvas.beginShape(); //base
  canvas.fill(0); 
  for (int i = 0; i < 3; ++i ) {
    canvas.vertex(basePts[i].x, basePts[i].y, basePts[i].z);
  }
  canvas.endShape(CLOSE);
  canvas.popMatrix(); ///  pyramid 2 (blk) end
  canvas.endDraw();

  blendMode(BLEND);
  image(canvas, 0, 0);
}
1 Like