高井です。
夏といえば夏休み。夏休みといえば自由研究。
自由研究気分で万華鏡を作ってみます。
使う言語はこちらで紹介したProcessingです。
やってみよう!!!
万華鏡の仕組み
参考サイト1
ニコン キッズアイランド「万華鏡のしくみを学ぼう」
https://www.jp.nikon.com/company/corporate/sp/kids/kaleidoscope/
まさに夏休みの自由研究でできそうな工作が紹介されています。
透明な筒にビーズを入れて周りを鏡で三角形に囲むことで、簡単な万華鏡が作れるみたいです。
参考サイト2
ナゾロジー「万華鏡はどうやって美しい幾何学模様を作るのか?秘密は三角形の角度!」
https://nazology.net/archives/130704
パンダの絵が鏡映しになっているイメージ図が分かりやすいです。
鏡は三角形が好ましいみたいです。
プログラミング方針
上記2サイトを踏まえ、ざっくりした方針を決めました↓
・ビーズクラスを作る
・位置や色が異なるビーズオブジェクトを大量に作る
・三角形のエリアに、大量生成したビーズを描画する
・隣にはそれを左右反転した三角形を、上下には上下反転した三角形を描画する
先駆者
なんと先駆者がいました!
https://github.com/abekzk/kaleidoscope
こちらのソースコードを参考にさせていただきました。
万華鏡作ってみた
※録画の都合でカクカクしています…すみません
ソースコード
main.pde
Ball[] balls = new Ball[50]; // ビーズ50個
Mirror[] mirrors = new Mirror[6]; // 鏡6枚
PGraphics texture; // 鏡に反射させる、元の絵(ビーズを描画するエリア)
void setup(){
size(600, 600, P2D);
// ビーズ初期化
for(int i = 0; i < 50; i++){
balls[i] = new Ball();
}
// テクスチャ初期化
texture = createGraphics(600, 600);
// 鏡初期化
for(int i = 0; i < 6; i++){
mirrors[i] = new Mirror(i, texture);
}
}
void draw(){
background(0);
// ビーズを描画する(元の絵になる)
drawTexture();
// 元の絵を反射した鏡を描画する
for(Mirror mirror:mirrors){
mirror.display();
}
// 録画のためこのフレームを保存
saveFrame("frames/####.png");
}
// 毎フレーム、ビーズ描画
void drawTexture(){
texture.beginDraw();
texture.background(255);
// ビーズをゆっくり回転させる
texture.translate(texture.width / 2, texture.height / 2);
texture.rotate(radians(millis()) / 50 % 360);
for(Ball ball:balls){
texture.shape(ball.shape, ball.x - texture.width / 2, ball.y - texture.height / 2);
}
texture.endDraw();
}
Ball.pde
// ビーズクラス
class Ball {
PShape shape; // 形(丸、三角形、四角形)
int x;
int y;
int size;
color c;
Ball(){
// 位置、サイズ、色をランダム生成
this.x = int(random(600));
this.y = int(random(600));
this.size = int(random(30, 60));
this.c = color(int(random(256)), int(random(256)), int(random(256)), int(random(256)));
// 形をランダム生成
int type = int(random(3));
if(type == 0){
shape = createShape(ELLIPSE, 0, 0, size, size);
}else if(type == 1){
shape = createShape(RECT, 0, 0, size, size);
}else if(type == 2){
shape = createShape(TRIANGLE, 0, 0, size, 0, size/2, size);
}
shape.setFill(c);
shape.setStroke(false);
}
}
Mirror.pde
// 鏡クラス
class Mirror{
PShape pShape; //描画する三角形
Mirror(int mirrorNum, PGraphics texture){
int r = 150; // 鏡のサイズ
int rad = 90 + 60 * mirrorNum; // 鏡の角度
int x = int(width / 2 + r * cos(radians(rad))); // 鏡のx座標
int y = int(height / 2 + r * sin(radians(rad))); // 鏡のy座標
textureMode(NORMAL);
pShape = createShape();
pShape.beginShape();
// 三角形に元の絵を貼り付ける設定
pShape.texture(texture);
// 三角形の縁をグレーで描画
pShape.stroke(200);
// 三角形の頂点の座標を描画する
for(int i = 0; i < 3; i++){
float theta = radians(60 * mirrorNum - 90 + 120 * i);
float thetaTexture = radians(-90 + 120 * i);
if(mirrorNum % 2 == 1){
// 奇数枚目ならテクスチャをそのまま貼り付ける
pShape.vertex(x + r * cos(theta), y + r * sin(theta), (cos(thetaTexture) + 1) * 0.5, (sin(thetaTexture) + 1) * 0.5);
}else{
// 偶数枚目ならテクスチャを反転して貼り付ける
pShape.vertex(x + r * cos(theta), y + r * sin(theta), 1 - (cos(thetaTexture) + 1) * 0.5, (sin(thetaTexture) + 1) * 0.5);
}
}
pShape.endShape(CLOSE);
}
// 毎フレーム、三角形を描画する
void display(){
shape(pShape);
}
}
ポイント
こだわりポイント
・半透明のビーズ(カワイイ)
・最終的に記事にするので、ソースコードを簡潔に書く
今後の改良ポイントや簡潔なソースコードのため断念したこと
・ビーズをぼんやり光らせたい(より"万華鏡"感ある見た目の研究)
・ハートとか星型とか、ビーズの形を増やしたい
・鏡が6枚しかないので、敷き詰めたい
以上、高井でした