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"],
},
]; 反発係数の異なる物体をキューブの中で動かす。 重力は無視している。
つまり、光がエネルギーを失いながら反射しているようなイメージ。