0

I programmed a hypercube in javascript using p5.js and works fine, but I would like to know how to rotate this hypercube in X axis using matrix rotations. I know that we can do this using standard functions in p5.js like rotateX (in the line 84), but I would like to do this using matrix rotations and isn't working.

Here's the code:

var points = [];
var distance = 2; //distance in w axis
var angle = 0;

//4D vector
class vector4D {
  constructor(x, y, z, w) {
    this.x = x;
    this.y = y;
    this.z = z;
    this.w = w;
  }
}

var rotatedVector = new vector4D();
var projectedVector = new vector4D();

//All points of a hypercube.
points[0] = new vector4D([-1], [-1], [-1], [1]);
points[1] = new vector4D([1], [-1], [-1], [1]);
points[2] = new vector4D([1], [1], [-1], [1]);
points[3] = new vector4D([-1], [1], [-1], [1]);
points[4] = new vector4D([-1], [-1], [1], [1]);
points[5] = new vector4D([1], [-1], [1], [1]);
points[6] = new vector4D([1], [1], [1], [1]);
points[7] = new vector4D([-1], [1], [1], [1]);
points[8] = new vector4D([-1], [-1], [-1], [-1]);
points[9] = new vector4D([1], [-1], [-1], [-1]);
points[10] = new vector4D([1], [1], [-1], [-1]);
points[11] = new vector4D([-1], [1], [-1], [-1]);
points[12] = new vector4D([-1], [-1], [1], [-1]);
points[13] = new vector4D([1], [-1], [1], [-1]);
points[14] = new vector4D([1], [1], [1], [-1]);
points[15] = new vector4D([-1], [1], [1], [-1]);

function setup() {
  createCanvas(600, 400, WEBGL);
}

//Multiply a 4x4 or 3x3 matrix with a vector
function multiply(a, b, size) {
  var vector = new vector4D();
  if (size == 4) {
    vector.x =
      a[0][0] * b.x + a[0][1] * b.y + a[0][2] * b.z + a[0][3] * b.w;
    vector.y =
      a[1][0] * b.x + a[1][1] * b.y + a[1][2] * b.z + a[1][3] * b.w;
    vector.z =
      a[2][0] * b.x + a[2][1] * b.y + a[2][2] * b.z + a[2][3] * b.w;
    vector.w =
      a[3][0] * b.x + a[3][1] * b.y + a[3][2] * b.z + a[3][3] * b.w;
  } else {
    vector.x = a[0][0] * b.x + a[0][1] * b.y + a[0][2] * b.z;
    vector.y = a[1][0] * b.x + a[1][1] * b.y + a[1][2] * b.z;
    vector.z = a[2][0] * b.x + a[2][1] * b.y + a[2][2] * b.z;
    vector.w = 1;
  }
  return vector;
}

//Connect all points of a hypercube
function connectDots(i, j, j2, projected) {
  line(
    projected[j + i].x,
    projected[j + i].y,
    projected[j + i].z,
    projected[j2 + i].x,
    projected[j2 + i].y,
    projected[j2 + i].z
  );
}

function draw() {
  background("blue");
  translate(0, 0);
  stroke(255);
  <!-- rotateX(-PI / 2); -->
  strokeWeight(1);

  //X, Y and Z are not used, but I put here to test rotations in all these axis
  var rotationMatrixX = [
    [1, 0, 0],
    [0, cos(angle), -sin(angle)],
    [0, sin(angle), cos(angle)],
  ];

  var rotationMatrixY = [
    [cos(angle), 0, sin(angle)],
    [0, 1, 0],
    [-sin(angle), 0, cos(angle)],
  ];

  var rotationMatrixZ = [
    [cos(angle), -sin(angle), 0],
    [sin(angle), cos(angle), 0],
    [0, 0, 1],
  ];

  var rotationMatrixXY = [
    [cos(angle), -sin(angle), 0, 0],
    [sin(angle), cos(angle), 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
  ];

  var rotationMatrixZW = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, cos(angle), -sin(angle)],
    [0, 0, sin(angle), cos(angle)],
  ];

  //All points rotated and projected to connect
  var projected = [16];

  for (i in points) {
    rotatedVector = multiply(
      rotationMatrixXY,
      points[i],
      rotationMatrixXY.length
    );
    rotatedVector = multiply(
      rotationMatrixZW,
      rotatedVector,
      rotationMatrixZW.length
    );

    //w perspective
    var w = 2 / (distance - rotatedVector.w);
    var projectionMatrix = [
      [w, 0, 0, 0],
      [0, w, 0, 0],
      [0, 0, w, 0],
    ];
    projectedVector = multiply(
      projectionMatrix,
      rotatedVector,
      projectionMatrix.length
    );
    projectedVector.x *= 25;
    projectedVector.y *= 25;
    projectedVector.z *= 25;
    projected[i] = projectedVector;
    point(projectedVector.x, projectedVector.y, projectedVector.z);
  }

  //Connecting all dots
  for (i = 0; i < 8; i++) {
    if (i < 4) {
      connectDots(0, i, i + 4, projected);
      connectDots(0, i, i + 8, projected);
      connectDots(0, i, (i + 1) % 4, projected);
      connectDots(0, i + 4, ((i + 1) % 4) + 4, projected);
      connectDots(8, i, i + 4, projected);
      connectDots(8, i, (i + 1) % 4, projected);
      connectDots(8, i + 4, ((i + 1) % 4) + 4, projected);
    }
    connectDots(0, i, i + 8, projected);
  }

  angle += 0.025;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
ggorlen
  • 44,755
  • 7
  • 76
  • 106
visionary
  • 51
  • 4
  • 1
    Unrelated to your main problem, but always use `for (let i` rather than `for (i`, otherwise you've inadvertently created a global. Better to use `let` rather than `var` to avoid many gotchas related to function-scoped variables. `for (i in points) {` should be `for (const point of points)` – ggorlen Apr 15 '23 at 22:21

0 Answers0