251208

const W = 800;
const H = 800;
const D = 800;
let palette = [];
let lightRays = [];

const MARGIN = 200;
const MAX_TRAIL_LENGTH = 30; // 軌跡
const BOUNDS = {
  left: -W / 2 + MARGIN,
  right: W / 2 - MARGIN,
  top: -H / 2 + MARGIN,
  bottom: H / 2 - MARGIN,
  near: -D / 2 + MARGIN,
  far: D / 2 - MARGIN,
};

function setup() {
  createCanvas(W, H, WEBGL);
  palette = colorArray[2].colors;
  background(palette[0]);
  frameRate(60);
  noFill();
  stroke(palette[4]);
  strokeWeight(2);

  let numRays = 100;
  for (let i = 0; i < numRays; i++) {
    let theta = random(TAU);
    let phi = random(TAU / 2);
    let speed = 20;

    // 球面座標から直交座標に変換
    let vx = speed * sin(phi) * cos(theta);
    let vy = speed * sin(phi) * sin(theta);
    let vz = speed * cos(phi);

    lightRays.push(new LightRay(0, H / 2, 0, vx, vy, vz, random(0.5, 1.0)));
  }
}

function draw() {
  orbitControl();
  background(palette[0]);
  for (let light of lightRays) {
    light.update();
    light.display();
  }
}

class LightRay {
  constructor(x, y, z, vx, vy, vz, restitution) {
    this.pos = createVector(x, y, z);
    this.vel = createVector(vx, vy, vz);
    this.restitution = restitution; // 反発係数
    this.trail = [];
  }

  // 衝突判定
  update() {
    this.pos.add(this.vel);

    // 下
    if (this.pos.y > BOUNDS.bottom) {
      this.pos.y = BOUNDS.bottom;
      this.vel.y *= -this.restitution;
    }
    // 上
    if (this.pos.y < BOUNDS.top) {
      this.pos.y = BOUNDS.top;
      this.vel.y *= -this.restitution;
    }
    // 左
    if (this.pos.x < BOUNDS.left) {
      this.pos.x = BOUNDS.left;
      this.vel.x *= -this.restitution;
    }
    // 右
    if (this.pos.x > BOUNDS.right) {
      this.pos.x = BOUNDS.right;
      this.vel.x *= -this.restitution;
    }
    // 手前
    if (this.pos.z < BOUNDS.near) {
      this.pos.z = BOUNDS.near;
      this.vel.z *= -this.restitution;
    }
    // 奥
    if (this.pos.z > BOUNDS.far) {
      this.pos.z = BOUNDS.far;
      this.vel.z *= -this.restitution;
    }

    // 軌跡
    this.trail.push(createVector(this.pos.x, this.pos.y, this.pos.z));
    // 軌跡を削除
    if (this.trail.length > MAX_TRAIL_LENGTH) {
      this.trail.shift();
    }
  }

  display() {
    if (this.trail.length > 1) {
      push();
      beginShape();
      for (let i = 0; i < this.trail.length; i++) {
        vertex(this.trail[i].x, this.trail[i].y, this.trail[i].z);
      }
      endShape();
      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"],
  },
];

反発係数の異なる物体をキューブの中で動かす。 重力は無視している。

つまり、光がエネルギーを失いながら反射しているようなイメージ。

Last Update :