Truncated Cube P3D

The following source code will create a truncated cube with the P3D renderer using beginShape()…endShape() with multiple vertices. Since it is difficult to add components to a GLWindow a separate JFrame controller window with Swing components was used. Two sliders provide alteration of cube size and crop length. Exploration with various settings result in interesting outputs. Cube rotation is achieved by click dragging the mouse in the main window. The control window is not closable; the app may be quit by closing the main window or hitting the ‘Quit’ button in the controller window. Using ‘Cmd-Q’ on a Mac will cause the runtime to hang due to thread destruction. This demo was developed on MacOS and has not been tested on other platforms.

Source code:

// LT = left top : RT = right top : RB = right bottom : LB = left bottom

import javax.swing.*;
import javax.swing.event.*;

float rotx = PI/4;
float roty = PI/4;

int s = 150;
int crop = s/2;

void buildControllerWnd() {
  JFrame frame = new JFrame("Controller Wnd");
  frame.setLayout(null);
  frame.setBounds(50, 100, 300, 270);

  // ====== Info Label ======= //
  JLabel infoLabel = new JLabel("<html>Click on main window to select it, then click and drag mouse to rotate cube.</html>");
  infoLabel.setBounds(30, 5, 250, 48);

  // ====== Size Label ======= //
  JLabel sizeLabel = new JLabel("Size");
  sizeLabel.setBounds(30, 55, 80, 24);

  // ====== Size Value ======= //
  JLabel sValue = new JLabel();
  sValue.setHorizontalAlignment(JLabel.CENTER);
  sValue.setBounds(220, 75, 50, 24);
  sValue.setText(Integer.toString(s));

  // ====== Size Slider ======= //
  JSlider sizeSlider = new JSlider(JSlider.HORIZONTAL, 0, 250, 150);
  sizeSlider.setBounds(30, 75, 200, 24);
  sizeSlider.addChangeListener(new ChangeListener() {
    void stateChanged(ChangeEvent changeEvent) {
      s = sizeSlider.getValue();
      sValue.setText(Integer.toString(sizeSlider.getValue()));
    }
  }
  );

  // ======== Crop Label ======== //
  JLabel cropLabel = new JLabel("Crop");
  cropLabel.setBounds(30, 100, 80, 24);

  // ======== Crop Value ======== //
  JLabel cropValue = new JLabel();
  cropValue.setHorizontalAlignment(JLabel.CENTER);
  cropValue.setBounds(220, 120, 50, 24);
  cropValue.setText(Integer.toString(crop));

  // ======== Crop Slider ======= //
  JSlider cropSlider = new JSlider(JSlider.HORIZONTAL, 0, 250, 75);
  cropSlider.setBounds(30, 120, 200, 24);
  cropSlider.addChangeListener(new ChangeListener() {
    void stateChanged(ChangeEvent changeEvent) {
      crop = cropSlider.getValue();
      cropValue.setText(Integer.toString(cropSlider.getValue()));
    }
  }
  );

  // ====== Quit Label ======= //
  JLabel quitLabel = new JLabel("<html>Close main window to quit the app or use Quit button below.  Do not use cmd-Q (will hang runtime).</html>");
  quitLabel.setBounds(30, 155, 250, 48);

  // ====== Quit Button ====== //
  JButton quitBtn = new JButton("Quit");
  quitBtn.setBounds(190, 210, 80, 24);
  quitBtn.addActionListener( e -> {
    exit();
  }
  );

  frame.add(infoLabel);
  frame.add(sizeLabel);
  frame.add(sValue);
  frame.add(sizeSlider);
  frame.add(cropLabel);
  frame.add(cropValue);
  frame.add(cropSlider);
  frame.add(quitLabel);
  frame.add(quitBtn);
  frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  frame.setVisible(true);
}

void setup() {
  size( 800, 800, P3D );
  surface.setTitle("Truncated Cube");
  strokeWeight(4);
  javax.swing.SwingUtilities.invokeLater(()-> {
    buildControllerWnd(); // Build components on EventDispatchThread
  }
  );
}

void draw() {
  background(128);
  translate(width/2.0, height/2.0, -100);
  rotateX(rotx);
  rotateY(roty);

  // ============ 6 Faces =========== //

  // Front face
  beginShape();
  fill(255, 0, 0); // Red
  vertex(-s, -s+crop, s);  // LT lower crop * -> Front LT Triangle
  vertex(-s+crop, -s, s);  // LT upper crop * -> Front LT Triangle
  vertex( s-crop, -s, s);  // RT upper crop * -> Front RT Triangle
  vertex( s, -s+crop, s);  // RT lower crop * -> Front RT Triangle
  vertex( s, s-crop, s);   // RB upper crop * -> Front RB Triangle
  vertex( s-crop, s, s);   // RB lower crop * -> Front RB Triangle
  vertex(-s+crop, s, s);   // LB lower crop * -> Front LB Triangle
  vertex(-s, s-crop, s);   // LB upper crop * -> Front LB Triangle
  endShape();

  // Back face
  beginShape();
  fill(255, 255, 0); // Yellow
  vertex( s, -s+crop, -s);  // LT lower crop * -> Back LT Triangle
  vertex( s-crop, -s, -s);  // LT upper crop * -> Back LT Triangle
  vertex(-s+crop, -s, -s);  // RT upper crop * -> Back RT Triangle
  vertex(-s, -s+crop, -s);  // RT lower crop * -> Back RT Triangle
  vertex(-s, s-crop, -s);   // RB upper crop * -> Back RB Triangle
  vertex(-s+crop, s, -s);   // RB lower crop * -> Back RB Triangle
  vertex( s-crop, s, -s);   // LB lower crop * -> Back LB Triangle
  vertex( s, s-crop, -s);   // LB upper crop * -> Back LB Triangle
  endShape();

  // Bottom face
  beginShape();
  fill(255, 0, 255);  // Magenta
  vertex(-s, s, s-crop);   // LT lower crop
  vertex(-s+crop, s, s);   // LT upper crop
  vertex( s-crop, s, s);   // RT upper crop
  vertex( s, s, s-crop);   // RT lower crop
  vertex( s, s, -s+crop);  // RB upper crop
  vertex( s-crop, s, -s);  // RB lower crop
  vertex(-s+crop, s, -s);  // LB lower crop
  vertex(-s, s, -s+crop);  // LB upper crop
  endShape();

  // Top face
  beginShape();
  fill(0, 255, 0);  // Green
  vertex(-s, -s, -s+crop);  // LT lower crop
  vertex(-s+crop, -s, -s);  // LT upper crop
  vertex( s-crop, -s, -s);  // RT upper crop
  vertex( s, -s, -s+crop);  // RT lower crop
  vertex( s, -s, s-crop);   // RB upper crop
  vertex( s-crop, -s, s);   // RB lower crop
  vertex(-s+crop, -s, s);   // LB lower crop
  vertex(-s, -s, s-crop);   // LB upper crop
  endShape();

  // Right face
  beginShape();
  fill(0, 0, 255); // Blue
  vertex( s, -s+crop, s);   // LT lower crop
  vertex( s, -s, s-crop);   // LT upper crop * -> Front RT Triangle
  vertex( s, -s, -s+crop);  // RT upper crop * -> Back LT Triangle
  vertex( s, -s+crop, -s);  // RT lower crop
  vertex( s, s-crop, -s);   // RB upper crop
  vertex( s, s, -s+crop);   // RB lower crop * -> Back LB Triangle
  vertex( s, s, s-crop);    // LB lower crop * -> Front RB Triangle
  vertex( s, s-crop, s);    // LB upper crop
  endShape();

  // Left face
  beginShape();
  fill(0, 255, 255); // Turquoise
  vertex(-s, -s+crop, -s);  // LT lower crop
  vertex(-s, -s, -s+crop);  // LT upper crop * -> Back RT Triangle
  vertex(-s, -s, s-crop);   // RT upper crop * -> Front LT Triangle
  vertex(-s, -s+crop, s);   // RT lower crop
  vertex(-s, s-crop, s);    // RB upper crop
  vertex(-s, s, s-crop);    // RB lower crop * -> Front LB Triangle
  vertex(-s, s, -s+crop);   // LB lower crop * -> Back RB Triangle
  vertex(-s, s-crop, -s);   // LB upper crop
  endShape();

  // ========== 8 Triangles =========== //

  beginShape();    // Front face LT triangle
  fill(255); // White
  vertex(-s, -s+crop, s);  // Front LT lower crop * -> LT Triangle
  vertex(-s+crop, -s, s);  // Front LT upper crop * -> LT Triangle
  vertex(-s, -s, s-crop);  // Left RT upper crop * -> LT Triangle
  endShape();

  beginShape();    // Front face RT triangle
  fill(255); // White
  vertex( s-crop, -s, s);  // Front RT upper crop * -> RT Triangle
  vertex( s, -s+crop, s);  // Front RT lower crop * -> RT Triangle
  vertex( s, -s, s-crop);  // Right LT upper crop * -> RT Triangle
  endShape();

  beginShape();    // Front face RB triangle
  fill(255); // White
  vertex( s, s-crop, s);   // Front RB upper crop * -> RB Triangle
  vertex( s-crop, s, s);   // Front RB lower crop * -> RB Triangle
  vertex( s, s, s-crop);   // Right LB lower crop * -> RB Triangle
  endShape();

  beginShape();    // Front face LB triangle
  fill(255); // White
  vertex(-s+crop, s, s);  // Front LB lower crop * -> LB Triangle
  vertex(-s, s-crop, s);  // Front LB upper crop * -> LB Triangle
  vertex(-s, s, s-crop);  // Left RB lower crop * -> LB Triangle
  endShape();

  beginShape();    // Back face LT triangle
  fill(255); // White
  vertex( s, -s+crop, -s);  // Back LT lower crop * -> LT Triangle
  vertex( s-crop, -s, -s);  // Back LT upper crop * -> LT Triangle
  vertex( s, -s, -s+crop);  // Left RT upper crop * -> LT Triangle
  endShape();

  beginShape();     // Back face RT triangle
  fill(255); // White
  vertex(-s+crop, -s, -s);  // Back RT upper crop * -> RT Triangle
  vertex(-s, -s+crop, -s);  // Back RT lower crop * -> RT Triangle
  vertex(-s, -s, -s+crop);  // Right LT upper crop * -> RT Triangle
  endShape();

  beginShape();    // Back face RB triangle
  fill(255); // White
  vertex(-s, s-crop, -s);  // Back RB upper crop * -> RB Triangle
  vertex(-s+crop, s, -s);  // Back RB lower crop * -> RB Triangle
  vertex(-s, s, -s+crop);  // Left LB lower crop * -> RB Triangle
  endShape();

  beginShape();    // Back face LB triangle
  fill(255); // White
  vertex( s-crop, s, -s);  // Back LB lower crop * -> LB Triangle
  vertex( s, s-crop, -s);  // Back LB upper crop * -> LB Triangle
  vertex( s, s, -s+crop);  // Right RB lower crop * -> LB Triangle
  endShape();
}

void mouseDragged() {
  float rate = 0.01;
  rotx += (pmouseY-mouseY) * rate;
  roty += (mouseX-pmouseX) * rate;
}

Normal Output:

Interesting Output: