251023

const W = 800;
const H = 800;

const GRID_SIZE = 150;
const GRID_R = 3;
const NUM_LINE = 15;
let COLS;
let ROWS;

let palette = [];
let gridPoints = [];
let innerAngles = [];

function setup() {
  createCanvas(W, H, WEBGL);
  palette = colorArray[2].colors;
  background(palette[0]);
  frameRate(60);
  COLS = floor(W / GRID_SIZE) + 1;
  ROWS = floor(H / GRID_SIZE) + 1;
}

function draw() {
  orbitControl();
  background(palette[0]);
  for (let i = 0; i < COLS; i++) {
    gridPoints[i] = [];
    for (let j = 0; j < ROWS; j++) {
      let freq = 0.1;
      push();
      let angle = frameCount * noise(i * 0.1, j * 0.1) * freq;
      let x = GRID_SIZE * i + (cos(angle) * GRID_SIZE) / GRID_R;
      let y = GRID_SIZE * j + (sin(angle) * GRID_SIZE) / GRID_R;
      let z = (sin(angle + i + j) * GRID_SIZE) / GRID_R;
      gridPoints[i][j] = createVector(x, y, z);
      pop();
    }
  }

  for (let i = 0; i < COLS - 1; i++) {
    innerAngles[i] = [];
    for (let j = 0; j < ROWS - 1; j++) {
      let P1 = gridPoints[i][j];
      let P2 = gridPoints[i][j + 1];
      let P3 = gridPoints[i + 1][j + 1];
      let P4 = gridPoints[i + 1][j];
      innerAngles[i][j] = {
        points: [P1, P2, P3, P4],
        angles: calculateAngles(P1, P2, P3, P4),
      };
    }
  }

  // 壁の位置
  for (let n = 0; n < 5; n++) {
    push();

    if (n == 0) {
      translate(-W / 2, -H / 2, 0);
      rotateY(TAU / 4);
    } else if (n == 1) {
      translate(-W / 2, -H / 2, 0);
      rotateY(TAU / 4);
      rotateX(TAU / 4);
    } else if (n == 2) {
      translate(W / 2, -H / 2, 0);
      rotateY(TAU / 4);
    } else if (n == 3) {
      translate(-W / 2, H / 2, 0);
      rotateX(-TAU / 4);
    } else if (n == 4) {
      translate(-W / 2, -H / 2, -W);
    }
    //vertex描画
    push();
    stroke(palette[4]);
    noFill();
    for (let i = 0; i < COLS - 1; i++) {
      for (let j = 0; j < ROWS - 1; j++) {
        beginShape();
        for (let k = 0; k < 4; k++) {
          // 元の頂点座標
          let p = innerAngles[i][j].points[k];
          vertex(p.x, p.y, p.z);
        }
        endShape(CLOSE);
        for (let k = 0; k < 4; k++) {
          drawLine(i, j, k + 1);
        }
      }
    }
    pop();
    pop();
  }

  // noLoop();
}

function calculateAngles(p1, p2, p3, p4) {
  let angles = [];
  // P1: (P1 -> P4) と (P1 -> P2) の角度
  let V_P1_to_P4 = p5.Vector.sub(p4, p1);
  let V_P1_to_P2 = p5.Vector.sub(p2, p1);
  angles[0] = V_P1_to_P4.angleBetween(V_P1_to_P2);
  // P2: (P2 -> P1) と (P2 -> P3) の角度
  let V_P2_to_P1 = p5.Vector.sub(p1, p2);
  let V_P2_to_P3 = p5.Vector.sub(p3, p2);
  angles[1] = V_P2_to_P1.angleBetween(V_P2_to_P3);
  // P3: (P3 -> P2) と (P3 -> P4) の角度
  let V_P3_to_P2 = p5.Vector.sub(p2, p3);
  let V_P3_to_P4 = p5.Vector.sub(p4, p3);
  angles[2] = V_P3_to_P2.angleBetween(V_P3_to_P4);
  // P4: (P4 -> P3) と (P4 -> P1) の角度
  let V_P4_to_P3 = p5.Vector.sub(p3, p4);
  let V_P4_to_P1 = p5.Vector.sub(p1, p4);
  angles[3] = V_P4_to_P3.angleBetween(V_P4_to_P1);
  return angles; // 180以上になることを考慮してない angles.map((a) => abs(a))
}

function drawLine(i, j, index) {
  let p = innerAngles[i][j];
  let pp = p.points[index - 1];
  let pa = p.angles[index - 1];

  push();
  // 60度以下でラインを引く
  const ninetyDegrees = TAU / 6;
  if (pa <= ninetyDegrees) {
    const vertices = p.points;
    push();
    const prevIdx = (index + 2) % 4;
    const nextIdx = index % 4;
    let subV1 = p5.Vector.sub(vertices[prevIdx], pp);
    let subV2 = p5.Vector.sub(vertices[nextIdx], pp);
    translate(pp.x, pp.y, pp.z);
    for (let i = 0; i < NUM_LINE; i++) {
      let direction1 = subV1
        .copy()
        .normalize()
        .mult(10 * (i + 1));
      let direction2 = subV2
        .copy()
        .normalize()
        .mult(10 * (i + 1));

      // directionの長さをsubVまで制限
      let maxLen1 = subV1.mag();
      let maxLen2 = subV2.mag();
      if (direction1.mag() > maxLen1) {
        direction1.setMag(maxLen1);
      }
      if (direction2.mag() > maxLen2) {
        direction2.setMag(maxLen2);
      }

      line(
        direction1.x,
        direction1.y,
        direction1.z,
        direction2.x,
        direction2.y,
        direction2.z
      );
    }
    pop();
  }
  // デバック用
  // push();
  // translate(pp.x, pp.y - index * 15, 0);
  // text(`P${index}`, 0, 0);
  // pop();
  // push();
  // translate(pp.x + 25, pp.y - index * 15, 0);
  // text(`${degrees(pa).toFixed(1)}°`, 0, 0);
  // pop();

  pop();
}

const colorArray = [
  {
    id: 0,
    colors: ["#253276", "#dfdad3", "#ffffff", "#000000"],
  },
  {
    id: 1,
    colors: ["#2E5400", "#dfdad3", "#ffffff", "#000000"],
  },
  {
    id: 2,
    colors: ["#253276", "#f9d3cc", "#f07433", "#437800", "#dfdad3"],
  },
];
  • angleBetween()で角度がπ/2以下のとき斜線を引く。

Last Update :