How to rotate a hypercube in javascript in X axis?

问题描述 投票:0回答:0

我使用 p5.js 在 javascript 中编写了一个超立方体并且工作正常,但我想知道如何使用矩阵旋转在 X 轴上旋转这个超立方体。我知道我们可以使用 p5.js 中的标准函数来做到这一点,比如 rotateX(在第 84 行),但我想使用矩阵旋转来做到这一点,但行不通。

代码如下:

  <head>
    <meta charset = "utf-8">
    <title>Hypercube</title>
  </head>
  <body>
  <script src = "https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
  <script>

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>
  </body>
</html>
javascript 3d rendering p5.js hypercube
© www.soinside.com 2019 - 2024. All rights reserved.