260125

const { animate } = anime;
const W = 800;
const H = 800;
let palette = [];
let animeValue = {
  count: 0,
};

function setup() {
  createCanvas(W, H, WEBGL);
  palette = colorArray[1].colors;
  background(palette[4]);
  animate(animeValue, {
    count: 1,
    duration: 10000,
    ease: 'inOutBack(2.59)',
    loop: true,
    loopDelay: 200,
    alternate: true,
  });
}

// p5.jsのトーラス関数の実装をコピーしてアレンジ
function drawTorus(radius = 200, tubeRadius = 100, detailX = 24, detailY = 16) {
  if (!radius || !tubeRadius) {
    return; // nothing to draw
  }
  let f = animeValue.count * TAU / 2;
  const tubeRatio = tubeRadius / radius;

  // 頂点を生成
  const vertices = [];
  const normals = [];

  for (let i = 0; i <= detailY; i++) {
    const v = i / detailY;
    const phi = TAU * v + f * sin(f * 0.2);
    const cosPhi = cos(phi);
    const sinPhi = sin(phi);
    const r = 1 + tubeRatio * cosPhi;

    for (let j = 0; j <= detailX; j++) {
      const u = j / detailX;
      const theta = TAU * u + f * 0.3;
      const cosTheta = cos(theta);
      const sinTheta = sin(theta);
      // 頂点位置
      const x = r * cosTheta * radius;
      const y = r * sinTheta * radius;
      const z = tubeRatio * sinPhi * radius;

      vertices.push({ x, y, z });

      // 法線ベクトル
      const nx = cosPhi * cosTheta;
      const ny = cosPhi * sinTheta;
      const nz = sinPhi;
      normals.push({ x: nx, y: ny, z: nz });
    }
  }

  // 面を描画
  for (let i = 0; i < detailY; i++) {
    for (let j = 0; j < detailX; j++) {
      const a = (detailX + 1) * i + j;
      const b = (detailX + 1) * (i + 1) + j;
      const c = (detailX + 1) * (i + 1) + (j + 1);
      const d = (detailX + 1) * i + (j + 1);

      fill(palette[(i + j) % palette.length]);
      // 最初の三角形
      beginShape(TRIANGLES);
      vertex(vertices[a].x, vertices[a].y, vertices[a].z);
      vertex(vertices[b].x, vertices[b].y, vertices[b].z);
      vertex(vertices[c].x, vertices[c].y, vertices[c].z);
      endShape();

      fill(palette[(i + j + floor(noise(i * 0.1, j * 0.1) * 10)) % palette.length]);
      // 2番目の三角形
      beginShape(TRIANGLES);
      vertex(vertices[a].x, vertices[a].y, vertices[a].z);
      vertex(vertices[c].x, vertices[c].y, vertices[c].z);
      vertex(vertices[d].x, vertices[d].y, vertices[d].z);
      endShape();
    }
  }
}

function draw() {
  background(palette[1]);
  orbitControl();
  noiseSeed(100);
  translate(30, 0, 0);
  rotateY(TAU / 16);
  rotateX(TAU / 16);
  drawTorus();
  // noLoop();
}

const colorArray = [
  {
    id: 0,
    colors: ['#253276', '#dfdad3', '#ffffff', '#000000'],
  },
  {
    id: 1,
    colors: [
      '#9dbdba',
      '#f8b042',
      '#e47763',
      '#253276',
      '#dfdad3',
      '#FFFFFF',
      '#000000',
    ],
  },
];

genuary2026 

Day25:Organic Geometry.

const { animate } = anime;
const W = 800;
const H = 800;
let palette = [];
let animeValue = {
  count: 0,
};

function setup() {
  createCanvas(W, H, WEBGL);
  palette = colorArray[1].colors;
  background(palette[4]);
  animate(animeValue, {
    count: 1,
    duration: 10000,
    ease: 'inOutBack(2.59)',
    loop: true,
    loopDelay: 200,
    alternate: true,
  });
}

// p5.jsのトーラス関数の実装をコピーしてアレンジ
function drawTorus(radius = 200, tubeRadius = 100, detailX = 24, detailY = 16) {
  if (!radius || !tubeRadius) {
    return; // nothing to draw
  }
  let f = animeValue.count * TAU / 2;
  const tubeRatio = tubeRadius / radius;

  // 頂点を生成
  const vertices = [];
  const normals = [];

  for (let i = 0; i <= detailY; i++) {
    const v = i / detailY;
    const phi = TAU * v + f * sin(f * 0.2);
    const cosPhi = cos(phi);
    const sinPhi = sin(phi);
    const r = 1 + tubeRatio * cosPhi;

    for (let j = 0; j <= detailX; j++) {
      const u = j / detailX;
      const theta = TAU * u + f * 0.3;
      const cosTheta = cos(theta);
      const sinTheta = sin(theta);
      // 頂点位置
      const x = r * cosTheta * radius;
      const y = r * sinTheta * radius;
      const z = tubeRatio * sinPhi * radius;

      vertices.push({ x, y, z });

      // 法線ベクトル
      const nx = cosPhi * cosTheta;
      const ny = cosPhi * sinTheta;
      const nz = sinPhi;
      normals.push({ x: nx, y: ny, z: nz });
    }
  }

  // 面を描画
  for (let i = 0; i < detailY; i++) {
    for (let j = 0; j < detailX; j++) {
      const a = (detailX + 1) * i + j;
      const b = (detailX + 1) * (i + 1) + j;
      const c = (detailX + 1) * (i + 1) + (j + 1);
      const d = (detailX + 1) * i + (j + 1);

      fill(palette[(i + j) % palette.length]);
      // 最初の三角形
      beginShape(TRIANGLES);
      vertex(vertices[a].x, vertices[a].y, vertices[a].z);
      vertex(vertices[b].x, vertices[b].y, vertices[b].z);
      vertex(vertices[c].x, vertices[c].y, vertices[c].z);
      endShape();

      fill(palette[(i + j + floor(noise(i * 0.1, j * 0.1) * 10)) % palette.length]);
      // 2番目の三角形
      beginShape(TRIANGLES);
      vertex(vertices[a].x, vertices[a].y, vertices[a].z);
      vertex(vertices[c].x, vertices[c].y, vertices[c].z);
      vertex(vertices[d].x, vertices[d].y, vertices[d].z);
      endShape();
    }
  }
}

function draw() {
  background(palette[1]);
  orbitControl();
  noiseSeed(100);
  translate(30, 0, 0);
  rotateY(TAU / 16);
  rotateX(TAU / 16);
  drawTorus();
  // noLoop();
}

const colorArray = [
  {
    id: 0,
    colors: ['#253276', '#dfdad3', '#ffffff', '#000000'],
  },
  {
    id: 1,
    colors: [
      '#9dbdba',
      '#f8b042',
      '#e47763',
      '#253276',
      '#dfdad3',
      '#FFFFFF',
      '#000000',
    ],
  },
];

Last Updated:

260125