let size = 60; let gridW = 0, gridH = 0; function setup() { createCanvas(2100, 2100); gridW = int(width / size); gridH = int(height / size); grid = []; list = []; // -------------------------------- // // 一定確率で壁の突起を設定する. // -------------------------------- // for (let i = 0; i < gridW; i++) { grid[i] = []; for (let j = 0; j < gridH; j++) { if (random() < 0.6) { grid[i].push(7); } else if (i == 0 || i == gridW - 1 || i == gridW - 2 || j == 0 || j == 1 || j == gridH - 1) { // 外周は突起にはしない grid[i].push(7); } else { grid[i].push(1); list.push([i, j, false]); } } } background(250); strokeWeight(1); // -------------------------------- // // 白マスを1つずつ走査していって周辺のマスを決める. // -------------------------------- // list.forEach(e => { let x = e[0]; let y = e[1]; if (x < gridW - 1) { // 右マスが白でない if (grid[x + 1][y] != 1) { // ここは右端 => 右マスを影と奥の壁(4)で仮決定 grid[x + 1][y] = 4; if (y < gridH - 1) { // 下マスも白 => 全面が影(6)に変更 if (grid[x][y + 1] == 1) grid[x + 1][y] = 6; // 右下マスも白 => 影と上面(8)に変更 if (grid[x + 1][y + 1] == 1) grid[x + 1][y] = 8; } } } if (y > 0) { // 上マスが白ではない if (grid[x][y - 1] != 1) { // 奥の壁と上面(2)で仮決定 grid[x][y - 1] = 2 if (x > 0) { // 左マスも白 => 上マスは上面(5)に変更 if (grid[x - 1][y] == 1) grid[x][y - 1] = 5; // 左上マスも白 => 影と上面の(8)に変更 if (grid[x - 1][y - 1] == 1) grid[x][y - 1] = 8; } if (x < gridW - 1) { // 右マスが白ではない & 右上マスが白ではない => 右上は上面 + 影(3) if (grid[x + 1][y] != 1 && grid[x + 1][y - 1] != 1) { grid[x + 1][y - 1] = 3; } } } } }); // -------------------------------- // // パターンに応じて各マスを描画. // -------------------------------- // for (let x = 0; x < gridW; x++) { for (let y = 0; y < gridH; y++) { let pattern = grid[x][y]; let colorFlg = false; if (x > 1 && y > 1 && x < gridW - 1 && y < gridH - 1 && grid[x - 1][y] != 1 && grid[x + 1][y] != 1 && grid[x][y - 1] != 1 && grid[x][y + 1] != 1) { if (random() < .5) { colorFlg = true; } } drawPattern(x, y, pattern, colorFlg); } } // -------------------------------- // // 白マスの境界線を必要に応じて描画. // -------------------------------- // stroke(0); list.forEach(e => { let x = e[0]; let y = e[1]; let p = x * size; let q = y * size; // 上マスが白ではない if (y > 0 && grid[x][y - 1] != 1) { line(p, q, p + size, q); } // 下マスが白ではない if (y < gridH - 1 && grid[x][y + 1] != 1) { line(p, q + size, p + size, q + size); } // 左マスが白ではない if (x > 0 && grid[x - 1][y] != 1) { line(p, q, p, q + size); } // 右マスが白 or 全面影ではない if (x < gridW - 1 && grid[x + 1][y] != 1 && grid[x + 1][y] != 6) { line(p + size, q, p + size, q + size); } }); } function drawPattern(x, y, pattern, colorFlg) { let p = x * size; let q = y * size; // (1) 白壁 if (pattern == 1) { if (colorFlg == true) { let rnd = random(); if(rnd < 0.25) { fill(88,112,88); } else if (rnd < 0.5) { fill(255,216,0); } else if (rnd < 0.75) { fill(88,116,152); } else { fill(232,104,80); } } else { fill(250); } noStroke(); rect(p, q, size, size); } // (2) 奥の壁 + 上面 else if (pattern == 2) { drawTOP(p, q); fill(250); stroke(250); triangle(p, q, p + size, q, p, q + size); stroke(30); point(p, q); line(p, q + size / 2, p + size / 2, q); line(p, q + size, p + size, q); } // (3) 上面 + 影 else if (pattern == 3) { drawTOP(p, q); fill(0); triangle(p, q + size, p + size, q, p + size, q + size); } // (4) 影 + 奥の壁 else if (pattern == 4) { drawWall(p, q); fill(0); stroke(0); triangle(p, q, p + size, q, p, q + size); } // (5) 上面 else if (pattern == 5) { drawTOP(p, q); } // (6) 影 else if (pattern == 6) { fill(0); stroke(0); rect(p, q, size, size); } // (7) 奥の壁 else if (pattern == 7) { drawWall(p, q); } // (8) 影 + 上面 else if (pattern == 8) { drawTOP(p, q); fill(0); triangle(p, q, p + size, q, p, q + size); } // エラー処理 else { print("ERROR: unknown pattern!!"); } } function drawTOP(p, q) { stroke(0); let num = 12; delta = size / num; for (let i = 0; i < num; i++) { line(p+1, q+1 + i * delta, p + size, q+1 + i * delta); } } function drawWall(p, q) { stroke(0); line(p, q + size / 2, p + size / 2, q); line(p, q + size, p + size, q); line(p + size / 2, q + size, p + size, q + size / 2); }
今週の作品メモ
📌 今週は、プライベートで毎週放送しているPodcastのラジオ番組がわけあってお休みということもあって前からやってみたかった、メディアアートの過去の大作を自分で再実装してみるというチャレンジです。
📌 選んだのは コードアートのパイオニアの一人と言われている Edward Zajecの1971年発表の作品 “Il Cubo” です。
📌 元の論文が公開されています。イタリア語です。
📌 一見、3D表現にも見える、凹凸のブロックとそれが生む影によって構成される作品はアルゴリズムに従って8つの基底パターンから1つを選びブロックごとに描画されます。まさにジェネラティブな作品です。
📌 ネットで検索しても先行実装例?はあまりありませんでした。その中で参考にした2つのコードへのリンクを載せておきます。
📌 コメントをたくさん残しておいたので、詳しくは説明しません。たくさんケースごとに分岐させてます。元の論文はもうちょっと賢い方法っぽい(?)
📌 調べながらメモった8つの基底パターン。たぶんソースコードと対応する、はず。
今週の雑談
📌 先週は #週刊p5js お休みしました。理由はこれに参加してたからです。
楽しそうな企画にエンジョイ勢として参加。まだw.i.p.だけど。
— ayato. (@dn0t_) 2020年5月16日
"RayMarching 01" by "ΛYATO" https://t.co/FEZKm8M6tq#NEORT #S1C002 #Shader1weekCompo
📌 今週はインプット習慣ということで、普段聞かないラジオとかテレビとか結構まとめて見た。
📌 特に自分的にインパクトがあったのは、GERAラジオでやってる「ラランドの声溜めラジオ」。それとYoutubede「太田伯山」を見た流れで、感化されて見た神田松之丞真打昇進襲名披露興行でやった「中村仲蔵」。
📌 個人的に、母親が大の伯山ファンなので意識的にあんまり伯山の講談は見ないようにしてきたのだけれど、悔しいことにこれが面白かった。
📌 はは~、深夜のラジオでひねくれた悪口ばっか言ってるイメージだったが、先にこっちを見ておくべきだったな、当たり前だけど。
📌 あとはこれはそこまで超絶面白かったってわけではないけど、さくっと楽しめるコンテンツという意味でAmazon Prime Video オリジナルドラマ「UPLOAD」が良かった。
今しがたAmazonオリジナルドラマ「UPLOAD」のシーズン1見終わったけど軽い感じで一気に見れてよかった。舞台は生前の記憶や魂をVR空間に移して、あの世とこの世で繋がれる近未来。事故るはずのない自動運転中の交通事故で死んだハンサムな主人公が死後VR空間で、オペレータである彼女と恋に落ちる話。 pic.twitter.com/46bmYvPeqA
— ayato. (@dn0t_) 2020年5月22日
📌 内容はツイートの通り。「近未来の設定の割にVRHMDがでかくね!?」みたいなことがずっと引っかかった。貧困層向けの「2G(ギガ)」ってVR空間があるのは面白かった。
📌 シーズン2はまだだけど、まあまた時間ができたら見ようかな。
📌 なんでかわからないけど、くだんのSNS誹謗中傷で人が自殺した件について3人とLINEでその話題になったけど、恋愛リアリティーショーってパッケージ自体が悲しいくらい人生の浪費だと思うのでまず見るべきではないし、何よりみんな1つの出来事からそれを一般化して教訓めいたものを見出したり意見したがったりしすぎだと思う。
📌 「占いなんて 怠け者の運命」って90年代にSMAPが歌ってたけど、そんな感じ。「くだらないことを話して笑いあって 分かり合うほうがなんか深い気がする」
📌 事務所を通す必要がないことで中間マージンや保証が必要ないという意味で、素人を扱う番組がどんどん増えているけど基本全部見ることはない。局にお金が集まらなくなった結果、どんどんテレビ制作のウーバーイーツ化が進むね。
📌 音楽はMura Masaが個人的にプチブーム!R.Y.C.もすばらしいけど1stのMura Masaもリズム感、音作り、ともに最高傑作だと思う。
📌 あと何よりジャケット!よくないですか!?調べたところこういうデザインコンセプト含めてMura Masa本人がプロデュースしているみたいですが、天は二物どころじゃないものを与えていませんか…。ここまでジャケットにぐっと来たのは久しぶりでした…。
今週のラジオ
〜お詫び〜
— A.M.SanGoCan (@am350can) 2020年5月21日
今週はtaigaのマイクがお亡くなりになったので収録・配信がお休みです🙇♂️
来週、いい音質でお送りできるようにそこそこの額するマイクを買った2人の様子をご覧ください。完全に深夜のノリでポチった。
後悔はしてない!!!#350can pic.twitter.com/0OsyBWBe3y
📌 ということで今週は以上です。ラジオがない分、話が長くなってしまいましたね。