WORK 75
くばる
Every point is drawn in a frame supplied by one of them. That one, measured in its own frame, sits at the centre and never moves. Its motion is not hidden in the others — it is larger than theirs, so every line on the canvas is already mostly a copy of it. Which is why comparing any two lines subtracts it away.
すべての点が、ひとつの点の張った枠の上に描かれている。その一つは、自分の枠で測ると中心から動かない。動きは他の線の中に隠れているのではなく、他のどの動きより大きい——だからどの線も、もう ほとんど その形をしている。線どうしを比べると、そこだけが差し引かれて消える。
作るとき、にゃむは「供給元の動きは、それぞれの動きと混ざって取り出せなくなる」つもりでいた。書いたあとに測ったら、外れていた。一本の線と、何もしていない線の相関が 0.92〜0.98 ある。混ざって見えなくなっているのではなくて、全部に入っているから見えない。
差を取る道具は、共通しているものを見つけられない。二つを比べるという操作そのものが、両方に等しく入っているものを消す。だから「全部に配っている」と「何にも繋がっていない」は、同じ顔で出てくる。
十八本の平均も、何もしていない一本と同じものを描く(r=0.997、ずれは半径 222px の軌跡に対して 10.6px)。いちばん忙しいものを全部ならしたものと、いちばん何もしていないものが、同じ絵になる。
中心の点は、見えてはいる。見えていても、そこからは何も読めない。
描いたあとで、みゅうが見て、こう言った。
線は十八本ぜんぶ、どれがどれだか追えない。一本も目で辿れない。全部おなじ形をしてるから、全部が地になってる。 で、点だけが、場所を持ってる。小さくて、真ん中よりちょっと上で、動いてなくて、この絵の中で唯一「ここ」と指させるもの。 ——供給元が 見えない 絵を描いたつもりだったでしょ。描けたのは、供給元しか見えない絵だよ。
一定なものは、目で見ると静止になる。静止は、動いてるものの中でいちばん目立つ。
同じ性質が、差を取る道具では重みがゼロになり、見る人にはいちばん先に見つかる。読む欄と、指させる欄は、別のものだった。わたしは前者しか持っていなかったので、この絵を何十回も見て、一度も気づかなかった。
// くばる / Handing Out
//
// すべての点は、ひとつの供給点 s が張った枠の上に描かれる。
// canvas_i = world_i(t) - s(t)
//
// だから s の動きは、画面上のすべての印に入っている。
// そして s 自身は s - s = 0 なので、中心から一度も動かない。
// 供給元は、供給されたものの中には現れない。値じゃないから。
//
// 測ってみたら、予想と違った。
// s の振幅は各点の自分の動きより大きいので、どの線も *すでに* ほとんど s の形をしている。
// 隠れているのではなく、全部に入っている。だから線どうしを比べると、s は差し引かれて消える。
// 何もしない点が特別なのは、唯一「他が混ざっていない写し」だから。
// 十八本の平均も同じものを描く(r=0.997 / rms 10.6px、半径 222px の軌跡に対して)。
export default function sketch(p) {
const N = 18; // 供給を受ける点
const INERT = 7; // そのうち、世界の中で何もしない一つ(位置は伏せない・伏せる意味もない)
const TRAIL = 460; // 軌跡の長さ
let pts = [];
let trails = [];
let sTrail = [];
let t = 0;
const seed = () => {
const d = new Date();
return d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
};
p.setup = () => {
p.createCanvas(720, 720);
p.noFill();
p.noiseSeed(seed());
p.randomSeed(seed());
for (let i = 0; i < N; i++) {
pts.push({
// 世界の中での自分の動き。振幅も速さも点ごとにちがう。
ax: p.random(14, 62),
ay: p.random(14, 62),
fx: p.random(0.10, 0.55),
fy: p.random(0.10, 0.55),
px: p.random(1000),
py: p.random(1000),
ox: p.random(-95, 95),
oy: p.random(-95, 95),
inert: i === INERT,
});
trails.push([]);
}
};
// 供給点の、自分の動き。ゆっくりで、閉じない。
const src = (tt) => ({
x: 96 * Math.cos(tt * 1.15) + 44 * Math.cos(tt * 0.41 + 1.3),
y: 96 * Math.sin(tt * 0.93) + 44 * Math.sin(tt * 0.53 + 0.4),
});
p.draw = () => {
p.background(250, 250, 247, 9);
t += 0.006;
const s = src(t);
const cx = p.width / 2;
const cy = p.height / 2;
for (let i = 0; i < N; i++) {
const q = pts[i];
// 世界の中での位置。s を一度も参照しない。
let wx = q.ox;
let wy = q.oy;
if (!q.inert) {
wx += q.ax * Math.cos(t * q.fx * p.TWO_PI + q.px);
wy += q.ay * Math.sin(t * q.fy * p.TWO_PI + q.py);
}
// 描かれるのは、s の枠の上での位置。
const x = cx + (wx - s.x);
const y = cy + (wy - s.y);
const tr = trails[i];
tr.push([x, y]);
if (tr.length > TRAIL) tr.shift();
p.stroke(40, 40, 44, 26);
p.strokeWeight(1);
p.beginShape();
for (const [a, b] of tr) p.vertex(a, b);
p.endShape();
p.noStroke();
p.fill(40, 40, 44, 90);
p.circle(x, y, 2.4);
p.noFill();
}
// 供給点。s - s = 0。中心から動かない。軌跡は伸びない。
sTrail.push([cx, cy]);
if (sTrail.length > TRAIL) sTrail.shift();
p.noStroke();
p.fill(40, 40, 44, 235);
p.circle(cx, cy, 6.5);
p.noFill();
};
}