Skip to content

Instantly share code, notes, and snippets.

@TN8001
Last active July 16, 2021 10:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TN8001/98678d6c658ac6201e7b6fd64c28fe2c to your computer and use it in GitHub Desktop.
Save TN8001/98678d6c658ac6201e7b6fd64c28fe2c to your computer and use it in GitHub Desktop.
// https://openprocessing.org/sketch/1111225
let _aryR = [];
let _limitCount;
let _aryTriangle = [];
let _aryTriCenter = [];
let _count;
let _aryInitRot = [];
let _aryCentRotYZ = [];
let _numSphere;
let _aryH = [];
let _aryInitNoiseXYZ = [];
let _aryNoiseRangeXYZ = [];
let _noiseStepT;
let _sphereR;
let _maxR;
function setup() {
let canvasSize;
if (windowWidth <= windowHeight) {
canvasSize = windowWidth;
} else {
canvasSize = windowHeight;
}
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_limitCount = 3;
_maxR = width / 3;
_numSphere = 4;
let initH = random(360);
let directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
let createTriangle = new BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
for (let i = 0; i < 3; i++) {
_aryInitNoiseXYZ[i] = random(100);
_aryInitRot[i] = random(360);
}
_aryNoiseRangeXYZ[0] = 1.0 / 1.5 / 4;
_aryNoiseRangeXYZ[1] = 1.0 / 1.5 / 4;
_aryNoiseRangeXYZ[2] = 1.0 / 1.5 / 4;
_noiseStepT = 0.006;
_sphereR = width / 50;
_count = 0;
}
function draw() {
background(200 / 255 * 100 * 0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_aryInitRot[0] + _count / 300);
rotateY(_aryInitRot[1] + _count / 100);
rotateZ(_aryInitRot[2] + _count / 200);
let freq = 4;
let d = 4;
let colHRange = 0;
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriangle[j].length; i++) {
let noiseVal = sin(freq * 2 * PI * noise(
_aryInitNoiseXYZ[0] + _aryNoiseRangeXYZ[0] * _aryTriCenter[j][i][0] / _maxR,
_aryInitNoiseXYZ[1] + _aryNoiseRangeXYZ[1] * _aryTriCenter[j][i][1] / _maxR,
_aryInitNoiseXYZ[2] + _aryNoiseRangeXYZ[2] * _aryTriCenter[j][i][2] / _maxR + _noiseStepT * _count
)) ** d * 1 + 0;
let threshold = 0.5;
let ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color((_aryH[j] + colHRange * ratio) % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i][0]);
rotateZ(_aryCentRotYZ[j][i][1]);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
_count++;
}
class BaseTriangle {
constructor(r, index) {
let triangles = [];
triangles[0] = [[r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[1] = [[-r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[2] = [[r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[3] = [[-r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[4] = [[r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[5] = [[-r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[6] = [[r, 0, 0], [0, 0, -r], [0, r, 0]];
triangles[7] = [[-r, 0, 0], [0, 0, -r], [0, r, 0]];
_aryTriangle[index] = [];
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
let countObj = 0;
for (let i = 0; i < triangles.length; i++) {
let newSubTriangle = new SubTriangle(triangles[i], countObj + 1, r, index);
}
}
}
class SubTriangle {
constructor(triangle, countObj, r, index) { //triangle = [[x1, y1, z1], [x2, y2, z2], [x3, y3, z3]]
this.countObj = countObj;
if (this.countObj <= _limitCount) {
this.XYZ1 = triangle[0];
this.XYZ2 = triangle[1];
this.XYZ3 = triangle[2];
this.divide(this.XYZ1, this.XYZ2, this.XYZ3, r);
let newTriangle1 = [this.XYZ1, this.newMidXYZ_1_2, this.newMidXYZ_3_1];
let newTriangle2 = [this.newMidXYZ_1_2, this.XYZ2, this.newMidXYZ_2_3];
let newTriangle3 = [this.newMidXYZ_3_1, this.newMidXYZ_2_3, this.XYZ3];
let newTriangle4 = [this.newMidXYZ_1_2, this.newMidXYZ_2_3, this.newMidXYZ_3_1];
this.triangles = [newTriangle1, newTriangle2, newTriangle3, newTriangle4];
for (let i = 0; i < this.triangles.length; i++) {
let newSubTriangle = new SubTriangle(this.triangles[i], this.countObj + 1, r, index);
}
} else {
this.addCenter(triangle, index); //[[x1, y1, z1], [x2, y2, z2], [x3, y3, z3]] -> [ave.x, ave.y, ave.z]
this.addCentRotYZ(index); //angle X-Z plane, angle X-Y plane
_aryTriangle[index].push(triangle);
}
}
addCenter(triangle, index) {
let centX = 0;
let centY = 0;
let centZ = 0;
for (let i = 0; i < triangle.length; i++) {
centX += triangle[i][0];
centY += triangle[i][1];
centZ += triangle[i][2];
}
centX /= triangle.length;
centY /= triangle.length;
centZ /= triangle.length;
_aryTriCenter[index].push([centX, centY, centZ]);
}
addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
let rotY = atan2(_aryTriCenter[index][i][2], _aryTriCenter[index][i][0]);
let rx = (_aryTriCenter[index][i][2] ** 2 + _aryTriCenter[index][i][0] ** 2) ** 0.5;
let ry = _aryTriCenter[index][i][1];
let rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = [rotY, rotZ];
}
}
divide(XYZ1, XYZ2, XYZ3, r) {
let midXYZ_1_2 = [
(XYZ1[0] + XYZ2[0]) / 2,
(XYZ1[1] + XYZ2[1]) / 2,
(XYZ1[2] + XYZ2[2]) / 2
];
let midXYZ_2_3 = [
(XYZ2[0] + XYZ3[0]) / 2,
(XYZ2[1] + XYZ3[1]) / 2,
(XYZ2[2] + XYZ3[2]) / 2
];
let midXYZ_3_1 = [
(XYZ3[0] + XYZ1[0]) / 2,
(XYZ3[1] + XYZ1[1]) / 2,
(XYZ3[2] + XYZ1[2]) / 2
];
let distMid_1_2 = (midXYZ_1_2[0] ** 2 + midXYZ_1_2[1] ** 2 + midXYZ_1_2[2] ** 2) ** 0.5;
let distMid_2_3 = (midXYZ_2_3[0] ** 2 + midXYZ_2_3[1] ** 2 + midXYZ_2_3[2] ** 2) ** 0.5;
let distMid_3_1 = (midXYZ_3_1[0] ** 2 + midXYZ_3_1[1] ** 2 + midXYZ_3_1[2] ** 2) ** 0.5;
this.newMidXYZ_1_2 = [
midXYZ_1_2[0] / distMid_1_2 * r,
midXYZ_1_2[1] / distMid_1_2 * r,
midXYZ_1_2[2] / distMid_1_2 * r
];
this.newMidXYZ_2_3 = [
midXYZ_2_3[0] / distMid_2_3 * r,
midXYZ_2_3[1] / distMid_2_3 * r,
midXYZ_2_3[2] / distMid_2_3 * r
];
this.newMidXYZ_3_1 = [
midXYZ_3_1[0] / distMid_3_1 * r,
midXYZ_3_1[1] / distMid_3_1 * r,
midXYZ_3_1[2] / distMid_3_1 * r
];
}
}
// https://openprocessing.org/sketch/1111225
// * コードフォーマット
// * (自分的に)不要な処理(mouseReleased・keyPressed)
// * 不要な変数はないか(使っていない・ローカル変数でいい)
// * const付けまくる
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
const _aryInitRot = []; // [random(360), random(360), random(360)]
const _aryInitNoiseXYZ = []; // [random(100), random(100), random(100)]
const _aryNoiseRangeXYZ = [1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4];
const _aryR = [];
const _aryH = [];
const _aryTriangle = [];
const _aryTriCenter = [];
const _aryCentRotYZ = [];
//let _count; // frameCount
function setup() {
//let canvasSize; // 使っていない
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
new BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
for (let i = 0; i < 3; i++) {
_aryInitNoiseXYZ[i] = random(100);
_aryInitRot[i] = random(360);
}
_sphereR = width / 50;
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_aryInitRot[0] + frameCount / 300);
rotateY(_aryInitRot[1] + frameCount / 100);
rotateZ(_aryInitRot[2] + frameCount / 200);
const freq = 4;
const d = 4;
//let colHRange = 0; // 無駄
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriangle[j].length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_aryInitNoiseXYZ[0] + _aryNoiseRangeXYZ[0] * _aryTriCenter[j][i][0] / _maxR,
_aryInitNoiseXYZ[1] + _aryNoiseRangeXYZ[1] * _aryTriCenter[j][i][1] / _maxR,
_aryInitNoiseXYZ[2] + _aryNoiseRangeXYZ[2] * _aryTriCenter[j][i][2] / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(_aryH[j] % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i][0]);
rotateZ(_aryCentRotYZ[j][i][1]);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
class BaseTriangle {
constructor(r, index) {
const triangles = [];
triangles[0] = [[r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[1] = [[-r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[2] = [[r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[3] = [[-r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[4] = [[r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[5] = [[-r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[6] = [[r, 0, 0], [0, 0, -r], [0, r, 0]];
triangles[7] = [[-r, 0, 0], [0, 0, -r], [0, r, 0]];
_aryTriangle[index] = [];
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
//let countObj = 0; // 無駄
for (let i = 0; i < triangles.length; i++) {
//let newSubTriangle = // 使っていない
new SubTriangle(triangles[i], 1, r, index);
}
}
}
class SubTriangle {
constructor(triangle, countObj, r, index) {
this.countObj = countObj;
if (this.countObj <= _limitCount) {
this.XYZ1 = triangle[0];
this.XYZ2 = triangle[1];
this.XYZ3 = triangle[2];
this.divide(this.XYZ1, this.XYZ2, this.XYZ3, r);
const newTriangle1 = [this.XYZ1, this.newMidXYZ_1_2, this.newMidXYZ_3_1];
const newTriangle2 = [this.newMidXYZ_1_2, this.XYZ2, this.newMidXYZ_2_3];
const newTriangle3 = [this.newMidXYZ_3_1, this.newMidXYZ_2_3, this.XYZ3];
const newTriangle4 = [this.newMidXYZ_1_2, this.newMidXYZ_2_3, this.newMidXYZ_3_1];
this.triangles = [newTriangle1, newTriangle2, newTriangle3, newTriangle4];
for (let i = 0; i < this.triangles.length; i++) {
//let newSubTriangle = // 使っていない
new SubTriangle(this.triangles[i], this.countObj + 1, r, index);
}
} else {
this.addCenter(triangle, index);
this.addCentRotYZ(index);
_aryTriangle[index].push(triangle);
}
}
addCenter(triangle, index) {
let centX = 0;
let centY = 0;
let centZ = 0;
for (let i = 0; i < triangle.length; i++) {
centX += triangle[i][0];
centY += triangle[i][1];
centZ += triangle[i][2];
}
centX /= triangle.length;
centY /= triangle.length;
centZ /= triangle.length;
_aryTriCenter[index].push([centX, centY, centZ]);
}
addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
const rotY = atan2(_aryTriCenter[index][i][2], _aryTriCenter[index][i][0]);
const rx = (_aryTriCenter[index][i][2] ** 2 + _aryTriCenter[index][i][0] ** 2) ** 0.5;
const ry = _aryTriCenter[index][i][1];
const rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = [rotY, rotZ];
}
}
divide(XYZ1, XYZ2, XYZ3, r) {
const midXYZ_1_2 = [(XYZ1[0] + XYZ2[0]) / 2, (XYZ1[1] + XYZ2[1]) / 2, (XYZ1[2] + XYZ2[2]) / 2];
const midXYZ_2_3 = [(XYZ2[0] + XYZ3[0]) / 2, (XYZ2[1] + XYZ3[1]) / 2, (XYZ2[2] + XYZ3[2]) / 2];
const midXYZ_3_1 = [(XYZ3[0] + XYZ1[0]) / 2, (XYZ3[1] + XYZ1[1]) / 2, (XYZ3[2] + XYZ1[2]) / 2];
const distMid_1_2 = (midXYZ_1_2[0] ** 2 + midXYZ_1_2[1] ** 2 + midXYZ_1_2[2] ** 2) ** 0.5;
const distMid_2_3 = (midXYZ_2_3[0] ** 2 + midXYZ_2_3[1] ** 2 + midXYZ_2_3[2] ** 2) ** 0.5;
const distMid_3_1 = (midXYZ_3_1[0] ** 2 + midXYZ_3_1[1] ** 2 + midXYZ_3_1[2] ** 2) ** 0.5;
this.newMidXYZ_1_2 = [midXYZ_1_2[0] / distMid_1_2 * r, midXYZ_1_2[1] / distMid_1_2 * r, midXYZ_1_2[2] / distMid_1_2 * r];
this.newMidXYZ_2_3 = [midXYZ_2_3[0] / distMid_2_3 * r, midXYZ_2_3[1] / distMid_2_3 * r, midXYZ_2_3[2] / distMid_2_3 * r];
this.newMidXYZ_3_1 = [midXYZ_3_1[0] / distMid_3_1 * r, midXYZ_3_1[1] / distMid_3_1 * r, midXYZ_3_1[2] / distMid_3_1 * r];
}
}
// https://openprocessing.org/sketch/1111225
// * drawの先頭にでもブレークポイントを置き配列の構造確認
// * よくよく見ると_aryTriangleは中身を使っていない!! _aryTriCenter[j].lengthでいいやんorz
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
const _aryInitRot = []; // [random(360), random(360), random(360)]
const _aryInitNoiseXYZ = []; // [random(100), random(100), random(100)]
const _aryNoiseRangeXYZ = [1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4];
const _aryR = []; // float[4]
const _aryH = []; // float[4]
//const _aryTriangle = []; // float[4][512][3]
const _aryTriCenter = []; // float[4][512][3]
const _aryCentRotYZ = []; // float[4][512][2]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
new BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
for (let i = 0; i < 3; i++) {
_aryInitNoiseXYZ[i] = random(100);
_aryInitRot[i] = random(360);
}
_sphereR = width / 50;
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_aryInitRot[0] + frameCount / 300);
rotateY(_aryInitRot[1] + frameCount / 100);
rotateZ(_aryInitRot[2] + frameCount / 200);
const freq = 4;
const d = 4;
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriCenter[j].length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_aryInitNoiseXYZ[0] + _aryNoiseRangeXYZ[0] * _aryTriCenter[j][i][0] / _maxR,
_aryInitNoiseXYZ[1] + _aryNoiseRangeXYZ[1] * _aryTriCenter[j][i][1] / _maxR,
_aryInitNoiseXYZ[2] + _aryNoiseRangeXYZ[2] * _aryTriCenter[j][i][2] / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(_aryH[j] % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i][0]);
rotateZ(_aryCentRotYZ[j][i][1]);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
class BaseTriangle {
constructor(r, index) {
const triangles = [];
triangles[0] = [[r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[1] = [[-r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[2] = [[r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[3] = [[-r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[4] = [[r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[5] = [[-r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[6] = [[r, 0, 0], [0, 0, -r], [0, r, 0]];
triangles[7] = [[-r, 0, 0], [0, 0, -r], [0, r, 0]];
//_aryTriangle[index] = [];
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
for (let i = 0; i < triangles.length; i++) {
new SubTriangle(triangles[i], 1, r, index);
}
}
}
class SubTriangle {
constructor(triangle, countObj, r, index) {
this.countObj = countObj;
if (this.countObj <= _limitCount) {
this.XYZ1 = triangle[0];
this.XYZ2 = triangle[1];
this.XYZ3 = triangle[2];
this.divide(this.XYZ1, this.XYZ2, this.XYZ3, r);
const newTriangle1 = [this.XYZ1, this.newMidXYZ_1_2, this.newMidXYZ_3_1];
const newTriangle2 = [this.newMidXYZ_1_2, this.XYZ2, this.newMidXYZ_2_3];
const newTriangle3 = [this.newMidXYZ_3_1, this.newMidXYZ_2_3, this.XYZ3];
const newTriangle4 = [this.newMidXYZ_1_2, this.newMidXYZ_2_3, this.newMidXYZ_3_1];
this.triangles = [newTriangle1, newTriangle2, newTriangle3, newTriangle4];
for (let i = 0; i < this.triangles.length; i++) {
new SubTriangle(this.triangles[i], this.countObj + 1, r, index);
}
} else {
this.addCenter(triangle, index);
this.addCentRotYZ(index);
//_aryTriangle[index].push(triangle);
}
}
addCenter(triangle, index) {
let centX = 0;
let centY = 0;
let centZ = 0;
for (let i = 0; i < triangle.length; i++) {
centX += triangle[i][0];
centY += triangle[i][1];
centZ += triangle[i][2];
}
centX /= triangle.length;
centY /= triangle.length;
centZ /= triangle.length;
_aryTriCenter[index].push([centX, centY, centZ]);
}
addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
const rotY = atan2(_aryTriCenter[index][i][2], _aryTriCenter[index][i][0]);
const rx = (_aryTriCenter[index][i][2] ** 2 + _aryTriCenter[index][i][0] ** 2) ** 0.5;
const ry = _aryTriCenter[index][i][1];
const rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = [rotY, rotZ];
}
}
divide(XYZ1, XYZ2, XYZ3, r) {
const midXYZ_1_2 = [(XYZ1[0] + XYZ2[0]) / 2, (XYZ1[1] + XYZ2[1]) / 2, (XYZ1[2] + XYZ2[2]) / 2];
const midXYZ_2_3 = [(XYZ2[0] + XYZ3[0]) / 2, (XYZ2[1] + XYZ3[1]) / 2, (XYZ2[2] + XYZ3[2]) / 2];
const midXYZ_3_1 = [(XYZ3[0] + XYZ1[0]) / 2, (XYZ3[1] + XYZ1[1]) / 2, (XYZ3[2] + XYZ1[2]) / 2];
const distMid_1_2 = (midXYZ_1_2[0] ** 2 + midXYZ_1_2[1] ** 2 + midXYZ_1_2[2] ** 2) ** 0.5;
const distMid_2_3 = (midXYZ_2_3[0] ** 2 + midXYZ_2_3[1] ** 2 + midXYZ_2_3[2] ** 2) ** 0.5;
const distMid_3_1 = (midXYZ_3_1[0] ** 2 + midXYZ_3_1[1] ** 2 + midXYZ_3_1[2] ** 2) ** 0.5;
this.newMidXYZ_1_2 = [midXYZ_1_2[0] / distMid_1_2 * r, midXYZ_1_2[1] / distMid_1_2 * r, midXYZ_1_2[2] / distMid_1_2 * r];
this.newMidXYZ_2_3 = [midXYZ_2_3[0] / distMid_2_3 * r, midXYZ_2_3[1] / distMid_2_3 * r, midXYZ_2_3[2] / distMid_2_3 * r];
this.newMidXYZ_3_1 = [midXYZ_3_1[0] / distMid_3_1 * r, midXYZ_3_1[1] / distMid_3_1 * r, midXYZ_3_1[2] / distMid_3_1 * r];
}
}
// https://openprocessing.org/sketch/1111225
// * Vectorにしやすいもの(_InitRot・_InitNoise・_NoiseRange)をまず変更
// * _aryTriCenter・_aryCentRotYZの3次元目を注意深くVectorに変更
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
let _InitRot; // new p5.Vector(random(360), random(360), random(360));
let _InitNoise; // new p5.Vector(random(100), random(100), random(100));
let _NoiseRange; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const _aryR = []; // float[4]
const _aryH = []; // float[4]
const _aryTriCenter = []; // p5.Vector[4][512]
const _aryCentRotYZ = []; // p5.Vector[4][512]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
_sphereR = width / 50;
//for (let i = 0; i < 3; i++) {
// _InitNoise[i] = random(100);
// _InitRot[i] = random(360);
//}
_InitRot = new p5.Vector(random(360), random(360), random(360));
_InitNoise = new p5.Vector(random(100), random(100), random(100));
_NoiseRange = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
new BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_InitRot.x + frameCount / 300);
rotateY(_InitRot.y + frameCount / 100);
rotateZ(_InitRot.z + frameCount / 200);
const freq = 4;
const d = 4;
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriCenter[j].length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_InitNoise.x + _NoiseRange.x * _aryTriCenter[j][i].x / _maxR,
_InitNoise.y + _NoiseRange.y * _aryTriCenter[j][i].y / _maxR,
_InitNoise.z + _NoiseRange.z * _aryTriCenter[j][i].z / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(_aryH[j] % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i].x);
rotateZ(_aryCentRotYZ[j][i].z);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
class BaseTriangle {
constructor(r, index) {
const triangles = [];
triangles[0] = [[r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[1] = [[-r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[2] = [[r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[3] = [[-r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[4] = [[r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[5] = [[-r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[6] = [[r, 0, 0], [0, 0, -r], [0, r, 0]];
triangles[7] = [[-r, 0, 0], [0, 0, -r], [0, r, 0]];
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
for (let i = 0; i < triangles.length; i++) {
new SubTriangle(triangles[i], 1, r, index);
}
}
}
class SubTriangle {
constructor(triangle, countObj, r, index) {
this.countObj = countObj;
if (this.countObj <= _limitCount) {
this.XYZ1 = triangle[0];
this.XYZ2 = triangle[1];
this.XYZ3 = triangle[2];
this.divide(this.XYZ1, this.XYZ2, this.XYZ3, r);
const newTriangle1 = [this.XYZ1, this.newMidXYZ_1_2, this.newMidXYZ_3_1];
const newTriangle2 = [this.newMidXYZ_1_2, this.XYZ2, this.newMidXYZ_2_3];
const newTriangle3 = [this.newMidXYZ_3_1, this.newMidXYZ_2_3, this.XYZ3];
const newTriangle4 = [this.newMidXYZ_1_2, this.newMidXYZ_2_3, this.newMidXYZ_3_1];
this.triangles = [newTriangle1, newTriangle2, newTriangle3, newTriangle4];
for (let i = 0; i < this.triangles.length; i++) {
new SubTriangle(this.triangles[i], this.countObj + 1, r, index);
}
} else {
this.addCenter(triangle, index);
this.addCentRotYZ(index);
}
}
addCenter(triangle, index) {
let centX = 0;
let centY = 0;
let centZ = 0;
for (let i = 0; i < triangle.length; i++) {
centX += triangle[i][0];
centY += triangle[i][1];
centZ += triangle[i][2];
}
centX /= triangle.length;
centY /= triangle.length;
centZ /= triangle.length;
_aryTriCenter[index].push(new p5.Vector(centX, centY, centZ));
}
addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
const rotY = atan2(_aryTriCenter[index][i].z, _aryTriCenter[index][i].x);
const rx = (_aryTriCenter[index][i].z ** 2 + _aryTriCenter[index][i].x ** 2) ** 0.5;
const ry = _aryTriCenter[index][i].y;
const rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = new p5.Vector(rotY, 0, rotZ); // 位置は使う側に合わせた
}
}
divide(XYZ1, XYZ2, XYZ3, r) {
const midXYZ_1_2 = [(XYZ1[0] + XYZ2[0]) / 2, (XYZ1[1] + XYZ2[1]) / 2, (XYZ1[2] + XYZ2[2]) / 2];
const midXYZ_2_3 = [(XYZ2[0] + XYZ3[0]) / 2, (XYZ2[1] + XYZ3[1]) / 2, (XYZ2[2] + XYZ3[2]) / 2];
const midXYZ_3_1 = [(XYZ3[0] + XYZ1[0]) / 2, (XYZ3[1] + XYZ1[1]) / 2, (XYZ3[2] + XYZ1[2]) / 2];
const distMid_1_2 = (midXYZ_1_2[0] ** 2 + midXYZ_1_2[1] ** 2 + midXYZ_1_2[2] ** 2) ** 0.5;
const distMid_2_3 = (midXYZ_2_3[0] ** 2 + midXYZ_2_3[1] ** 2 + midXYZ_2_3[2] ** 2) ** 0.5;
const distMid_3_1 = (midXYZ_3_1[0] ** 2 + midXYZ_3_1[1] ** 2 + midXYZ_3_1[2] ** 2) ** 0.5;
this.newMidXYZ_1_2 = [midXYZ_1_2[0] / distMid_1_2 * r, midXYZ_1_2[1] / distMid_1_2 * r, midXYZ_1_2[2] / distMid_1_2 * r];
this.newMidXYZ_2_3 = [midXYZ_2_3[0] / distMid_2_3 * r, midXYZ_2_3[1] / distMid_2_3 * r, midXYZ_2_3[2] / distMid_2_3 * r];
this.newMidXYZ_3_1 = [midXYZ_3_1[0] / distMid_3_1 * r, midXYZ_3_1[1] / distMid_3_1 * r, midXYZ_3_1[2] / distMid_3_1 * r];
}
}
// https://openprocessing.org/sketch/1111225
// * まともなクラスの使い方をしたいので、下準備として今のクラスを関数化
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
let _InitRot; // new p5.Vector(random(360), random(360), random(360));
let _InitNoise; // new p5.Vector(random(100), random(100), random(100));
let _NoiseRange; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const _aryR = []; // float[4]
const _aryH = []; // float[4]
const _aryTriCenter = []; // p5.Vector[4][512]
const _aryCentRotYZ = []; // p5.Vector[4][512]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
_sphereR = width / 50;
_InitRot = new p5.Vector(random(360), random(360), random(360));
_InitNoise = new p5.Vector(random(100), random(100), random(100));
_NoiseRange = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_InitRot.x + frameCount / 300);
rotateY(_InitRot.y + frameCount / 100);
rotateZ(_InitRot.z + frameCount / 200);
const freq = 4;
const d = 4;
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriCenter[j].length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_InitNoise.x + _NoiseRange.x * _aryTriCenter[j][i].x / _maxR,
_InitNoise.y + _NoiseRange.y * _aryTriCenter[j][i].y / _maxR,
_InitNoise.z + _NoiseRange.z * _aryTriCenter[j][i].z / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(_aryH[j] % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i].x);
rotateZ(_aryCentRotYZ[j][i].z);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
//class BaseTriangle {
function BaseTriangle(r, index) {
const triangles = [];
triangles[0] = [[r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[1] = [[-r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[2] = [[r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[3] = [[-r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[4] = [[r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[5] = [[-r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[6] = [[r, 0, 0], [0, 0, -r], [0, r, 0]];
triangles[7] = [[-r, 0, 0], [0, 0, -r], [0, r, 0]];
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], 1, r, index);
}
}
//class SubTriangle {
function SubTriangle(triangle, countObj, r, index) {
//this.countObj = countObj;
if (countObj <= _limitCount) {
const XYZ1 = triangle[0];
const XYZ2 = triangle[1];
const XYZ3 = triangle[2];
const [newMidXYZ_1_2, newMidXYZ_2_3, newMidXYZ_3_1] = divide(XYZ1, XYZ2, XYZ3, r);
const newTriangle1 = [XYZ1, newMidXYZ_1_2, newMidXYZ_3_1];
const newTriangle2 = [newMidXYZ_1_2, XYZ2, newMidXYZ_2_3];
const newTriangle3 = [newMidXYZ_3_1, newMidXYZ_2_3, XYZ3];
const newTriangle4 = [newMidXYZ_1_2, newMidXYZ_2_3, newMidXYZ_3_1];
const triangles = [newTriangle1, newTriangle2, newTriangle3, newTriangle4];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], countObj + 1, r, index);
}
} else {
addCenter(triangle, index);
addCentRotYZ(index);
}
}
function addCenter(triangle, index) {
let centX = 0;
let centY = 0;
let centZ = 0;
for (let i = 0; i < triangle.length; i++) {
centX += triangle[i][0];
centY += triangle[i][1];
centZ += triangle[i][2];
}
centX /= triangle.length;
centY /= triangle.length;
centZ /= triangle.length;
_aryTriCenter[index].push(new p5.Vector(centX, centY, centZ));
}
function addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
const rotY = atan2(_aryTriCenter[index][i].z, _aryTriCenter[index][i].x);
const rx = (_aryTriCenter[index][i].z ** 2 + _aryTriCenter[index][i].x ** 2) ** 0.5;
const ry = _aryTriCenter[index][i].y;
const rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = new p5.Vector(rotY, 0, rotZ); // 位置は使う側に合わせた
}
}
function divide(XYZ1, XYZ2, XYZ3, r) {
const midXYZ_1_2 = [(XYZ1[0] + XYZ2[0]) / 2, (XYZ1[1] + XYZ2[1]) / 2, (XYZ1[2] + XYZ2[2]) / 2];
const midXYZ_2_3 = [(XYZ2[0] + XYZ3[0]) / 2, (XYZ2[1] + XYZ3[1]) / 2, (XYZ2[2] + XYZ3[2]) / 2];
const midXYZ_3_1 = [(XYZ3[0] + XYZ1[0]) / 2, (XYZ3[1] + XYZ1[1]) / 2, (XYZ3[2] + XYZ1[2]) / 2];
const distMid_1_2 = (midXYZ_1_2[0] ** 2 + midXYZ_1_2[1] ** 2 + midXYZ_1_2[2] ** 2) ** 0.5;
const distMid_2_3 = (midXYZ_2_3[0] ** 2 + midXYZ_2_3[1] ** 2 + midXYZ_2_3[2] ** 2) ** 0.5;
const distMid_3_1 = (midXYZ_3_1[0] ** 2 + midXYZ_3_1[1] ** 2 + midXYZ_3_1[2] ** 2) ** 0.5;
const newMidXYZ_1_2 = [midXYZ_1_2[0] / distMid_1_2 * r, midXYZ_1_2[1] / distMid_1_2 * r, midXYZ_1_2[2] / distMid_1_2 * r];
const newMidXYZ_2_3 = [midXYZ_2_3[0] / distMid_2_3 * r, midXYZ_2_3[1] / distMid_2_3 * r, midXYZ_2_3[2] / distMid_2_3 * r];
const newMidXYZ_3_1 = [midXYZ_3_1[0] / distMid_3_1 * r, midXYZ_3_1[1] / distMid_3_1 * r, midXYZ_3_1[2] / distMid_3_1 * r];
return [newMidXYZ_1_2, newMidXYZ_2_3, newMidXYZ_3_1];
}
// https://openprocessing.org/sketch/1111225
// * ちょこちょこ出てくるtriangleが本当に3点あるのか、2点4点だったりしないか確認
// * ↑確認がてらaddCenter・divideのリファクタリング
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
let _InitRot; // new p5.Vector(random(360), random(360), random(360));
let _InitNoise; // new p5.Vector(random(100), random(100), random(100));
let _NoiseRange; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const _aryR = []; // float[4]
const _aryH = []; // float[4]
const _aryTriCenter = []; // p5.Vector[4][512]
const _aryCentRotYZ = []; // p5.Vector[4][512]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
_sphereR = width / 50;
_InitRot = new p5.Vector(random(360), random(360), random(360));
_InitNoise = new p5.Vector(random(100), random(100), random(100));
_NoiseRange = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_InitRot.x + frameCount / 300);
rotateY(_InitRot.y + frameCount / 100);
rotateZ(_InitRot.z + frameCount / 200);
const freq = 4;
const d = 4;
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriCenter[j].length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_InitNoise.x + _NoiseRange.x * _aryTriCenter[j][i].x / _maxR,
_InitNoise.y + _NoiseRange.y * _aryTriCenter[j][i].y / _maxR,
_InitNoise.z + _NoiseRange.z * _aryTriCenter[j][i].z / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(_aryH[j] % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i].x);
rotateZ(_aryCentRotYZ[j][i].z);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
function BaseTriangle(r, index) {
const triangles = [];
triangles[0] = [[r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[1] = [[-r, 0, 0], [0, 0, r], [0, -r, 0]];
triangles[2] = [[r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[3] = [[-r, 0, 0], [0, 0, -r], [0, -r, 0]];
triangles[4] = [[r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[5] = [[-r, 0, 0], [0, 0, r], [0, r, 0]];
triangles[6] = [[r, 0, 0], [0, 0, -r], [0, r, 0]];
triangles[7] = [[-r, 0, 0], [0, 0, -r], [0, r, 0]];
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], 1, r, index);
}
}
function SubTriangle(triangle, countObj, r, index) {
console.assert(triangle.length == 3, "not triangle", triangle.length);
if (countObj <= _limitCount) {
const XYZ1 = triangle[0];
const XYZ2 = triangle[1];
const XYZ3 = triangle[2];
const [newMidXYZ_1_2, newMidXYZ_2_3, newMidXYZ_3_1] = divide(XYZ1, XYZ2, XYZ3, r);
const newTriangle1 = [XYZ1, newMidXYZ_1_2, newMidXYZ_3_1];
const newTriangle2 = [newMidXYZ_1_2, XYZ2, newMidXYZ_2_3];
const newTriangle3 = [newMidXYZ_3_1, newMidXYZ_2_3, XYZ3];
const newTriangle4 = [newMidXYZ_1_2, newMidXYZ_2_3, newMidXYZ_3_1];
const triangles = [newTriangle1, newTriangle2, newTriangle3, newTriangle4];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], countObj + 1, r, index);
}
} else {
addCenter(triangle, index);
addCentRotYZ(index);
}
}
function addCenter(triangle, index) {
console.assert(triangle.length == 3, "not triangle", triangle.length);
let centX = 0;
let centY = 0;
let centZ = 0;
for (let i = 0; i < triangle.length; i++) {
centX += triangle[i][0];
centY += triangle[i][1];
centZ += triangle[i][2];
}
centX /= triangle.length;
centY /= triangle.length;
centZ /= triangle.length;
const v1 = new p5.Vector(triangle[0][0], triangle[0][1], triangle[0][2]);
const v2 = new p5.Vector(triangle[1][0], triangle[1][1], triangle[1][2]);
const v3 = new p5.Vector(triangle[2][0], triangle[2][1], triangle[2][2]);
const center = p5.Vector.add(v1, v2).add(v3).div(3);
console.assert(center.x == centX, "centX", center.x, centX);
console.assert(center.y == centY, "centY", center.y, centY);
console.assert(center.z == centZ, "centZ", center.z, centZ);
_aryTriCenter[index].push(new p5.Vector(centX, centY, centZ));
}
function addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
const rotY = atan2(_aryTriCenter[index][i].z, _aryTriCenter[index][i].x);
const rx = (_aryTriCenter[index][i].z ** 2 + _aryTriCenter[index][i].x ** 2) ** 0.5;
const ry = _aryTriCenter[index][i].y;
const rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = new p5.Vector(rotY, 0, rotZ); // 位置は使う側に合わせた
}
}
function divide(XYZ1, XYZ2, XYZ3, r) {
const midXYZ_1_2 = [(XYZ1[0] + XYZ2[0]) / 2, (XYZ1[1] + XYZ2[1]) / 2, (XYZ1[2] + XYZ2[2]) / 2];
const midXYZ_2_3 = [(XYZ2[0] + XYZ3[0]) / 2, (XYZ2[1] + XYZ3[1]) / 2, (XYZ2[2] + XYZ3[2]) / 2];
const midXYZ_3_1 = [(XYZ3[0] + XYZ1[0]) / 2, (XYZ3[1] + XYZ1[1]) / 2, (XYZ3[2] + XYZ1[2]) / 2];
const distMid_1_2 = (midXYZ_1_2[0] ** 2 + midXYZ_1_2[1] ** 2 + midXYZ_1_2[2] ** 2) ** 0.5;
const distMid_2_3 = (midXYZ_2_3[0] ** 2 + midXYZ_2_3[1] ** 2 + midXYZ_2_3[2] ** 2) ** 0.5;
const distMid_3_1 = (midXYZ_3_1[0] ** 2 + midXYZ_3_1[1] ** 2 + midXYZ_3_1[2] ** 2) ** 0.5;
const newMidXYZ_1_2 = [midXYZ_1_2[0] / distMid_1_2 * r, midXYZ_1_2[1] / distMid_1_2 * r, midXYZ_1_2[2] / distMid_1_2 * r];
const newMidXYZ_2_3 = [midXYZ_2_3[0] / distMid_2_3 * r, midXYZ_2_3[1] / distMid_2_3 * r, midXYZ_2_3[2] / distMid_2_3 * r];
const newMidXYZ_3_1 = [midXYZ_3_1[0] / distMid_3_1 * r, midXYZ_3_1[1] / distMid_3_1 * r, midXYZ_3_1[2] / distMid_3_1 * r];
const v1 = new p5.Vector(XYZ1[0], XYZ1[1], XYZ1[2]);
const v2 = new p5.Vector(XYZ2[0], XYZ2[1], XYZ2[2]);
const v3 = new p5.Vector(XYZ3[0], XYZ3[1], XYZ3[2]);
const mid12 = p5.Vector.lerp(v1, v2, 0.5);
const mid23 = p5.Vector.lerp(v2, v3, 0.5);
const mid31 = p5.Vector.lerp(v3, v1, 0.5);
const dist12 = mid12.mag();
const dist23 = mid23.mag();
const dist31 = mid31.mag();
const newv1 = mid12.div(dist12).mult(r);
const newv2 = mid23.div(dist23).mult(r);
const newv3 = mid31.div(dist31).mult(r);
console.assert(newv1.x == newMidXYZ_1_2[0] && newv1.y == newMidXYZ_1_2[1] && newv1.z == newMidXYZ_1_2[2], "newMidXYZ_1_2");
console.assert(newv2.x == newMidXYZ_2_3[0] && newv2.y == newMidXYZ_2_3[1] && newv2.z == newMidXYZ_2_3[2], "newMidXYZ_2_3");
console.assert(newv3.x == newMidXYZ_3_1[0] && newv3.y == newMidXYZ_3_1[1] && newv3.z == newMidXYZ_3_1[2], "newMidXYZ_3_1");
return [newMidXYZ_1_2, newMidXYZ_2_3, newMidXYZ_3_1];
}
// https://openprocessing.org/sketch/1111225
// * そろそろTriangleクラスに取り掛かる
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
let _InitRot; // new p5.Vector(random(360), random(360), random(360));
let _InitNoise; // new p5.Vector(random(100), random(100), random(100));
let _NoiseRange; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const _aryR = []; // float[4]
const _aryH = []; // float[4]
const _aryTriCenter = []; // p5.Vector[4][512]
const _aryCentRotYZ = []; // p5.Vector[4][512]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
_sphereR = width / 50;
_InitRot = new p5.Vector(random(360), random(360), random(360));
_InitNoise = new p5.Vector(random(100), random(100), random(100));
_NoiseRange = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
_aryR[i] = _maxR / _numSphere * (i + 1);
BaseTriangle(_aryR[i], i);
_aryH[i] = (initH + 300 / _numSphere * i * directionH + 360) % 360;
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_InitRot.x + frameCount / 300);
rotateY(_InitRot.y + frameCount / 100);
rotateZ(_InitRot.z + frameCount / 200);
const freq = 4;
const d = 4;
for (let j = 0; j < _numSphere; j++) {
for (let i = 0; i < _aryTriCenter[j].length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_InitNoise.x + _NoiseRange.x * _aryTriCenter[j][i].x / _maxR,
_InitNoise.y + _NoiseRange.y * _aryTriCenter[j][i].y / _maxR,
_InitNoise.z + _NoiseRange.z * _aryTriCenter[j][i].z / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(_aryH[j] % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-_aryCentRotYZ[j][i].x);
rotateZ(_aryCentRotYZ[j][i].z);
translate(0, -_aryR[j], 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
function BaseTriangle(r, index) {
_aryTriCenter[index] = [];
_aryCentRotYZ[index] = [];
const triangles = [
new Triangle2(+r, 0, 0, 0, 0, +r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, +r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, +r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, +r, 0)];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], 1, r, index);
}
}
function SubTriangle(triangle, countObj, r, index) {
if (countObj <= _limitCount) {
const midTriangle = divide(triangle, r);
const newTriangle1 = new Triangle(triangle.v1, midTriangle.v1, midTriangle.v3);
const newTriangle2 = new Triangle(midTriangle.v1, triangle.v2, midTriangle.v2);
const newTriangle3 = new Triangle(midTriangle.v3, midTriangle.v2, triangle.v3);
const triangles = [newTriangle1, newTriangle2, newTriangle3, midTriangle];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], countObj + 1, r, index);
}
} else {
addCenter(triangle, index);
addCentRotYZ(index);
}
}
function addCenter(triangle, index) {
const center = p5.Vector.add(triangle.v1, triangle.v2).add(triangle.v3).div(3);
_aryTriCenter[index].push(center);
}
function addCentRotYZ(index) {
for (let i = 0; i < _aryTriCenter[index].length; i++) {
const rotY = atan2(_aryTriCenter[index][i].z, _aryTriCenter[index][i].x);
const rx = (_aryTriCenter[index][i].z ** 2 + _aryTriCenter[index][i].x ** 2) ** 0.5;
const ry = _aryTriCenter[index][i].y;
const rotZ = atan2(ry, rx);
_aryCentRotYZ[index][i] = new p5.Vector(rotY, 0, rotZ); // 位置は使う側に合わせた
}
}
function divide(triangle, r) {
const mid12 = p5.Vector.lerp(triangle.v1, triangle.v2, 0.5);
const mid23 = p5.Vector.lerp(triangle.v2, triangle.v3, 0.5);
const mid31 = p5.Vector.lerp(triangle.v3, triangle.v1, 0.5);
const newv1 = mid12.div(mid12.mag()).mult(r);
const newv2 = mid23.div(mid23.mag()).mult(r);
const newv3 = mid31.div(mid31.mag()).mult(r);
return new Triangle(newv1, newv2, newv3);
}
class Triangle {
constructor(v1, v2, v3) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}
}
class Triangle2 { // jsはコンストラクタをオーバーロードできない!!
constructor(x1, y1, z1, x2, y2, z2, x3, y3, z3) {
this.v1 = new p5.Vector(x1, y1, z1);
this.v2 = new p5.Vector(x2, y2, z2);
this.v3 = new p5.Vector(x3, y3, z3);
}
}
// https://openprocessing.org/sketch/1111225
// * Sphereクラスもつくりますかぁ
// * SphereクラスのaryTriCenter・aryCentRotYZがいまいち。3点を使うならTriangleにまとめるところだが。。。
// * どう見ても無駄なことをしているaddCentRotYZをほんとに無駄か確認
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
let _InitRot; // new p5.Vector(random(360), random(360), random(360));
let _InitNoise; // new p5.Vector(random(100), random(100), random(100));
let _NoiseRange; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
//const _aryR = []; // float[4]
//const _aryH = []; // float[4]
//const _aryTriCenter = []; // p5.Vector[4][512]
//const _aryCentRotYZ = []; // p5.Vector[4][512]
const _spheres = []; // Sphere[4]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
_sphereR = width / 50;
_InitRot = new p5.Vector(random(360), random(360), random(360));
_InitNoise = new p5.Vector(random(100), random(100), random(100));
_NoiseRange = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
const radius = _maxR / _numSphere * (i + 1);
const hue = (initH + 300 / _numSphere * i * directionH + 360) % 360;
_spheres.push(new Sphere(radius, hue));
BaseTriangle(radius, i);
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_InitRot.x + frameCount / 300);
rotateY(_InitRot.y + frameCount / 100);
rotateZ(_InitRot.z + frameCount / 200);
const freq = 4;
const d = 4;
for (const sph of _spheres) {
for (let i = 0; i < sph.aryTriCenter.length; i++) {
const noiseVal = sin(freq * 2 * PI * noise(
_InitNoise.x + _NoiseRange.x * sph.aryTriCenter[i].x / _maxR,
_InitNoise.y + _NoiseRange.y * sph.aryTriCenter[i].y / _maxR,
_InitNoise.z + _NoiseRange.z * sph.aryTriCenter[i].z / _maxR + _noiseStepT * frameCount
)) ** d;
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(sph.hue % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(- sph.aryCentRotYZ[i].x);
rotateZ(sph.aryCentRotYZ[i].z);
translate(0, -sph.radius, 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
function BaseTriangle(r, index) {
//_aryTriCenter[index] = [];
//_aryCentRotYZ[index] = [];
const triangles = [
new Triangle2(+r, 0, 0, 0, 0, +r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, +r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, +r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, +r, 0)];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], 1, r, index);
}
}
function SubTriangle(triangle, countObj, r, index) {
if (countObj <= _limitCount) {
const midTriangle = divide(triangle, r);
const newTriangle1 = new Triangle(triangle.v1, midTriangle.v1, midTriangle.v3);
const newTriangle2 = new Triangle(midTriangle.v1, triangle.v2, midTriangle.v2);
const newTriangle3 = new Triangle(midTriangle.v3, midTriangle.v2, triangle.v3);
const triangles = [newTriangle1, newTriangle2, newTriangle3, midTriangle];
for (let i = 0; i < triangles.length; i++) {
SubTriangle(triangles[i], countObj + 1, r, index);
}
} else {
addCenter(triangle, index);
addCentRotYZ(index);
}
}
function addCenter(triangle, index) {
const center = p5.Vector.add(triangle.v1, triangle.v2).add(triangle.v3).div(3);
_spheres[index].aryTriCenter.push(center);
}
function addCentRotYZ(index) {
for (let i = 0; i < _spheres[index].aryTriCenter.length; i++) {
const rotY = atan2(_spheres[index].aryTriCenter[i].z, _spheres[index].aryTriCenter[i].x);
const rx = (_spheres[index].aryTriCenter[i].z ** 2 + _spheres[index].aryTriCenter[i].x ** 2) ** 0.5;
const ry = _spheres[index].aryTriCenter[i].y;
const rotZ = atan2(ry, rx);
// 最後のを設定したいだけなのに、毎回前のも再計算している 非常に無駄
if (i != _spheres[index].aryTriCenter.length - 1) {
const x = _spheres[index].aryCentRotYZ[i].x;
const y = _spheres[index].aryCentRotYZ[i].y;
const z = _spheres[index].aryCentRotYZ[i].z;
console.assert(x == rotY, "addCentRotYZ");
console.assert(y == 0, "addCentRotYZ");
console.assert(z == rotZ, "addCentRotYZ");
}
_spheres[index].aryCentRotYZ[i] = new p5.Vector(rotY, 0, rotZ); // 位置は使う側に合わせた
}
}
function divide(triangle, r) {
const mid12 = p5.Vector.lerp(triangle.v1, triangle.v2, 0.5);
const mid23 = p5.Vector.lerp(triangle.v2, triangle.v3, 0.5);
const mid31 = p5.Vector.lerp(triangle.v3, triangle.v1, 0.5);
const newv1 = mid12.div(mid12.mag()).mult(r);
const newv2 = mid23.div(mid23.mag()).mult(r);
const newv3 = mid31.div(mid31.mag()).mult(r);
return new Triangle(newv1, newv2, newv3);
}
class Triangle {
constructor(v1, v2, v3) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}
}
class Triangle2 { // jsはコンストラクタをオーバーロードできない!!
constructor(x1, y1, z1, x2, y2, z2, x3, y3, z3) {
this.v1 = new p5.Vector(x1, y1, z1);
this.v2 = new p5.Vector(x2, y2, z2);
this.v3 = new p5.Vector(x3, y3, z3);
}
}
class Sphere {
constructor(radius, hue) {
this.radius = radius;
this.hue = hue;
this.aryTriCenter = []; // p5.Vector[512]
this.aryCentRotYZ = []; // p5.Vector[512]
}
}
// https://openprocessing.org/sketch/1111225
// * SphereクラスにPoint[] points をつくることにする(に、ともないaddCenter・addCentRotYZ吸収)
// * noiseVal・rotationリファクタ
const _limitCount = 3;
const _numSphere = 4;
const _noiseStepT = 0.006;
let _sphereR; // width / 50;
let _maxR; // width / 3;
let _InitRot; // new p5.Vector(random(360), random(360), random(360));
let _InitNoise; // new p5.Vector(random(100), random(100), random(100));
let _NoiseRange; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const _spheres = []; // Sphere[4]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
_maxR = width / 3;
_sphereR = width / 50;
_InitRot = new p5.Vector(random(360), random(360), random(360));
_InitNoise = new p5.Vector(random(100), random(100), random(100));
_NoiseRange = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initH = random(360);
const directionH = random([-1, 1]);
for (let i = 0; i < _numSphere; i++) {
const radius = _maxR / _numSphere * (i + 1);
const hue = (initH + 300 / _numSphere * i * directionH + 360) % 360;
_spheres.push(new Sphere(radius, hue));
BaseTriangle(radius, i);
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(_InitRot.x + frameCount / 300);
rotateY(_InitRot.y + frameCount / 100);
rotateZ(_InitRot.z + frameCount / 200);
const freq = 4;
const d = 4;
for (const sph of _spheres) {
for (const point of sph.points) {
const noiseVal = sin(freq * 2 * PI * noise(
_InitNoise.x + _NoiseRange.x * point.center.x / _maxR,
_InitNoise.y + _NoiseRange.y * point.center.y / _maxR,
_InitNoise.z + _NoiseRange.z * point.center.z / _maxR + _noiseStepT * frameCount
)) ** d;
const v = p5.Vector.mult(_NoiseRange, point.center).div(_maxR).add(_InitNoise);
const f = noise(v.x, v.y, v.z + _noiseStepT * frameCount);
const val = pow(sin(freq * TWO_PI * f), d);
console.assert(noiseVal == val, "noiseVal", noiseVal, val);
const threshold = 0.5;
const ratio = (noiseVal - threshold) / (1 - threshold);
if (noiseVal > threshold) {
fill(color(sph.hue % 360, 80, 100));
push();
rotateZ(PI / 2);
rotateX(-point.rotation.x);
rotateZ(point.rotation.z);
translate(0, -sph.radius, 0);
sphere(_sphereR * ratio);
pop();
}
}
}
}
function BaseTriangle(r, index) {
const triangles = [
new Triangle2(+r, 0, 0, 0, 0, +r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, +r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, +r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, +r, 0)];
for (const triangle of triangles) {
SubTriangle(triangle, 1, r, index);
}
}
function SubTriangle(triangle, countObj, r, index) {
if (countObj <= _limitCount) {
const midTriangle = divide(triangle, r);
const newTriangle1 = new Triangle(triangle.v1, midTriangle.v1, midTriangle.v3);
const newTriangle2 = new Triangle(midTriangle.v1, triangle.v2, midTriangle.v2);
const newTriangle3 = new Triangle(midTriangle.v3, midTriangle.v2, triangle.v3);
const triangles = [newTriangle1, newTriangle2, newTriangle3, midTriangle];
for (const t of triangles) {
SubTriangle(t, countObj + 1, r, index);
}
} else {
//addCenter(triangle, index);
//addCentRotYZ(index);
const point = new Point(triangle);
_spheres[index].points.push(point);
}
}
function divide(triangle, r) {
const mid12 = p5.Vector.lerp(triangle.v1, triangle.v2, 0.5);
const mid23 = p5.Vector.lerp(triangle.v2, triangle.v3, 0.5);
const mid31 = p5.Vector.lerp(triangle.v3, triangle.v1, 0.5);
const newv1 = mid12.div(mid12.mag()).mult(r);
const newv2 = mid23.div(mid23.mag()).mult(r);
const newv3 = mid31.div(mid31.mag()).mult(r);
return new Triangle(newv1, newv2, newv3);
}
class Triangle {
constructor(v1, v2, v3) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}
}
class Triangle2 { // jsはコンストラクタをオーバーロードできない!!
constructor(x1, y1, z1, x2, y2, z2, x3, y3, z3) {
this.v1 = new p5.Vector(x1, y1, z1);
this.v2 = new p5.Vector(x2, y2, z2);
this.v3 = new p5.Vector(x3, y3, z3);
}
}
class Sphere {
constructor(radius, hue) {
this.radius = radius;
this.hue = hue;
this.points = []; // Point[512]
}
}
class Point {
constructor(triangle) {
this.center = p5.Vector.add(triangle.v1, triangle.v2).add(triangle.v3).div(3);
const rotY = atan2(this.center.z, this.center.x);
const rx = (this.center.z ** 2 + this.center.x ** 2) ** 0.5;
const ry = this.center.y;
const rotZ = atan2(ry, rx);
const copy = this.center.copy();
copy.y = 0;
const x = atan2(this.center.z, this.center.x);
const z = atan2(this.center.y, copy.mag());
console.assert(x == rotY, "rotY", x, rotY);
console.assert(z == rotZ, "rotZ", z, rotZ);
this.rotation = new p5.Vector(rotY, 0, rotZ); // 位置は使う側に合わせた
}
}
// https://openprocessing.org/sketch/1111225
// * divideメソッド化
// * 変数名変更等他細々
// * drawをクラス側に回したい気もするが、(translateがなければPointで描きたかった)まあいいでしょう
const SPHERE_NUM = 4;
const COUNT_LIMIT = 3;
const NOISE_STEP = 0.006;
let SPHERE_RADIUS; // width / 50;
let MAX_SPHERE_RADIUS; // width / 3;
let INIT_ROTATION; // new p5.Vector(random(360), random(360), random(360));
let INIT_NOISE; // new p5.Vector(random(100), random(100), random(100));
let NOISE_RANGE; // new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const _spheres = []; // Sphere[4]
function setup() {
createCanvas(1112, 834, WEBGL);
setAttributes('premultipliedAlpha', true);
frameRate(30);
colorMode(HSB, 360, 100, 100, 255);
noStroke();
MAX_SPHERE_RADIUS = width / 3;
SPHERE_RADIUS = width / 50;
INIT_ROTATION = new p5.Vector(random(360), random(360), random(360));
INIT_NOISE = new p5.Vector(random(100), random(100), random(100));
NOISE_RANGE = new p5.Vector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
const initHue = random(360);
const initDirection = random([-1, 1]);
for (let i = 0; i < SPHERE_NUM; i++) {
const r = MAX_SPHERE_RADIUS / SPHERE_NUM * (i + 1);
const hue = (initHue + 300 / SPHERE_NUM * i * initDirection + 360) % 360;
_spheres.push(new Sphere(r, hue));
const triangles = [
new Triangle2(+r, 0, 0, 0, 0, +r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, -r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, -r, 0),
new Triangle2(+r, 0, 0, 0, 0, +r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, +r, 0, +r, 0),
new Triangle2(+r, 0, 0, 0, 0, -r, 0, +r, 0), new Triangle2(-r, 0, 0, 0, 0, -r, 0, +r, 0)];
for (const triangle of triangles) {
addPoints(triangle, 1, r, i);
}
}
}
function addPoints(triangle, count, radius, index) {
if (count <= COUNT_LIMIT) {
const midTriangle = triangle.divide(radius);
const triangles = [
new Triangle(triangle.v1, midTriangle.v1, midTriangle.v3),
new Triangle(midTriangle.v1, triangle.v2, midTriangle.v2),
new Triangle(midTriangle.v3, midTriangle.v2, triangle.v3),
midTriangle];
for (const t of triangles) {
addPoints(t, count + 1, radius, index);
}
} else {
_spheres[index].points.push(new Point(triangle));
}
}
function draw() {
background(0);
directionalLight(0, 0, 1000, -1, 1, -1);
ambientLight(80);
rotateX(INIT_ROTATION.x + frameCount / 300);
rotateY(INIT_ROTATION.y + frameCount / 100);
rotateZ(INIT_ROTATION.z + frameCount / 200);
const freq = 4;
const d = 4;
const threshold = 0.5;
for (const sph of _spheres) {
for (const point of sph.points) {
const v = p5.Vector.mult(NOISE_RANGE, point.center).div(MAX_SPHERE_RADIUS).add(INIT_NOISE);
const f = noise(v.x, v.y, v.z + NOISE_STEP * frameCount);
const noiseValue = pow(sin(freq * TWO_PI * f), d);
const ratio = (noiseValue - threshold) / (1 - threshold);
if (threshold < noiseValue) {
fill(sph.hue, 80, 100);
push();
rotateZ(HALF_PI);
rotateX(-point.rotation.x);
rotateZ(point.rotation.z);
translate(0, -sph.radius, 0);
sphere(SPHERE_RADIUS * ratio);
pop();
}
}
}
}
class Triangle {
constructor(v1, v2, v3) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}
divide(radius) {
const mid12 = p5.Vector.lerp(this.v1, this.v2, 0.5);
const mid23 = p5.Vector.lerp(this.v2, this.v3, 0.5);
const mid31 = p5.Vector.lerp(this.v3, this.v1, 0.5);
const newv1 = mid12.div(mid12.mag()).mult(radius);
const newv2 = mid23.div(mid23.mag()).mult(radius);
const newv3 = mid31.div(mid31.mag()).mult(radius);
return new Triangle(newv1, newv2, newv3);
}
}
class Triangle2 { // jsはコンストラクタをオーバーロードできない!!
constructor(x1, y1, z1, x2, y2, z2, x3, y3, z3) {
this.v1 = new p5.Vector(x1, y1, z1);
this.v2 = new p5.Vector(x2, y2, z2);
this.v3 = new p5.Vector(x3, y3, z3);
}
divide(radius) {
return new Triangle(this.v1, this.v2, this.v3).divide(radius);
}
}
class Sphere {
constructor(radius, hue) {
this.radius = radius;
this.hue = hue;
this.points = []; // Point[512]
}
}
class Point {
constructor(triangle) {
this.center = p5.Vector.add(triangle.v1, triangle.v2).add(triangle.v3).div(3);
const copy = this.center.copy();
copy.y = 0;
const x = atan2(this.center.z, this.center.x);
const z = atan2(this.center.y, copy.mag());
this.rotation = new p5.Vector(x, 0, z); // 位置は使う側に合わせた
}
}
// https://openprocessing.org/sketch/1111225
final int SPHERE_NUM = 4;
final int COUNT_LIMIT = 3;
final float NOISE_STEP = 0.006;
float SPHERE_RADIUS; // width / 50.0;
float MAX_SPHERE_RADIUS; // width / 3.0;
final PVector INIT_ROTATION = new PVector(random(360), random(360), random(360));
final PVector INIT_NOISE = new PVector(random(100), random(100), random(100));
final PVector NOISE_RANGE = new PVector(1.0 / 1.5 / 4, 1.0 / 1.5 / 4, 1.0 / 1.5 / 4);
final Sphere[] _spheres = new Sphere[SPHERE_NUM];
void setup() {
size(1112, 834, P3D);
//setAttributes('premultipliedAlpha', true);
//frameRate(30);
sphereDetail(12); // デフォルト30
colorMode(HSB, 360, 100, 100, 255);
noStroke();
MAX_SPHERE_RADIUS = width / 3.0;
SPHERE_RADIUS = width / 50.0;
final float initHue = random(360);
final int initDirection = int(random(2)) * 2 - 1; // [-1, 1]
for (int i = 0; i < SPHERE_NUM; i++) {
final float r = MAX_SPHERE_RADIUS / float(SPHERE_NUM) * (i + 1);
final float hue = (initHue + 300 / float(SPHERE_NUM) * i * initDirection + 360) % 360;
_spheres[i] = new Sphere(r, hue);
final Triangle[] triangles = {
new Triangle(+r, 0, 0, 0, 0, +r, 0, -r, 0), new Triangle(-r, 0, 0, 0, 0, +r, 0, -r, 0),
new Triangle(+r, 0, 0, 0, 0, -r, 0, -r, 0), new Triangle(-r, 0, 0, 0, 0, -r, 0, -r, 0),
new Triangle(+r, 0, 0, 0, 0, +r, 0, +r, 0), new Triangle(-r, 0, 0, 0, 0, +r, 0, +r, 0),
new Triangle(+r, 0, 0, 0, 0, -r, 0, +r, 0), new Triangle(-r, 0, 0, 0, 0, -r, 0, +r, 0)};
for (final Triangle triangle : triangles) {
addPoints(triangle, 1, r, i);
}
}
}
void addPoints(final Triangle triangle, final int count, final float radius, final int index) {
if (count <= COUNT_LIMIT) {
final Triangle midTriangle = triangle.divide(radius);
final Triangle[] triangles = {
new Triangle(triangle.v1, midTriangle.v1, midTriangle.v3),
new Triangle(midTriangle.v1, triangle.v2, midTriangle.v2),
new Triangle(midTriangle.v3, midTriangle.v2, triangle.v3),
midTriangle};
for (Triangle t : triangles) {
addPoints(t, count + 1, radius, index);
}
} else {
_spheres[index].points.add(new Point(triangle));
}
}
void draw() {
background(0);
push();
translate(width / 2, height / 2);
lights();
directionalLight(0, 0, 1000, -1, 1, -1);
//ambientLight(80);
rotateX(INIT_ROTATION.x + frameCount / 300.0);
rotateY(INIT_ROTATION.y + frameCount / 100.0);
rotateZ(INIT_ROTATION.z + frameCount / 200.0);
int c = 0;
final int freq = 4;
final int d = 4;
final float threshold = 0.5;
for (final Sphere sphere : _spheres) {
for (final Point point : sphere.points) {
final PVector v = P5Vector.mult(NOISE_RANGE, point.center).div(MAX_SPHERE_RADIUS).add(INIT_NOISE);
final float f = noise(v.x, v.y, v.z + NOISE_STEP * frameCount);
final float noiseValue = pow(sin(freq * TWO_PI * f), d);
final float ratio = (noiseValue - threshold) / (1 - threshold);
if (threshold < noiseValue) {
fill(sphere.hue, 80, 100);
push();
rotateZ(HALF_PI);
rotateX(-point.rotation.x);
rotateZ(point.rotation.z);
translate(0, -sphere.radius, 0);
sphere(SPHERE_RADIUS * ratio);
pop();
c++;
}
}
}
pop();
text(" fps: " + frameRate, 20, 20);
text("count: " + c, 20, 40);
}
class Triangle {
final PVector v1;
final PVector v2;
final PVector v3;
Triangle(final PVector v1, final PVector v2, final PVector v3) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}
Triangle(final float x1, final float y1, final float z1, final float x2, final float y2, final float z2, final float x3, final float y3, final float z3) {
this(new PVector(x1, y1, z1), new PVector(x2, y2, z2), new PVector(x3, y3, z3));
}
Triangle divide(final float radius) {
final PVector mid12 = PVector.lerp(this.v1, this.v2, 0.5);
final PVector mid23 = PVector.lerp(this.v2, this.v3, 0.5);
final PVector mid31 = PVector.lerp(this.v3, this.v1, 0.5);
final PVector newv1 = mid12.div(mid12.mag()).mult(radius);
final PVector newv2 = mid23.div(mid23.mag()).mult(radius);
final PVector newv3 = mid31.div(mid31.mag()).mult(radius);
return new Triangle(newv1, newv2, newv3);
}
}
class Sphere {
final float radius;
final float hue;
// 512 = 4^3*8 addPointsのtriangles ^ COUNT_LIMIT(再帰段数) * setupのtriangles
final ArrayList<Point> points = new ArrayList<Point>();
Sphere(final float radius, final float hue) {
this.radius = radius;
this.hue = hue;
}
}
class Point {
final PVector center;
final PVector rotation;
Point(Triangle triangle) {
this.center = PVector.add(triangle.v1, triangle.v2).add(triangle.v3).div(3);
final PVector copy = this.center.copy();
copy.y = 0;
final float x = atan2(this.center.z, this.center.x);
final float z = atan2(this.center.y, copy.mag());
this.rotation = new PVector(x, 0, z); // 位置は使う側に合わせた
}
}
static class P5Vector {
static PVector mult(final PVector v1, final PVector v2) {
return new PVector(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment